Al ejecutar Jasmine en un navegador real, noté que el componente de dispositivo TestBed no se destruye en DOM y persiste después de que finalizan las pruebas:
Aquí hay un componente probado:
@Component({ selector: 'test-app', template: `<div>Test</div>`, }) class Test {}Y una prueba ( plunk ).
let component; let fixture; let element; beforeAll(() => { TestBed.resetTestEnvironment(); TestBed.initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); }); beforeEach(() => { TestBed.configureTestingModule({ declarations: [Test], }) .compileComponents(); fixture = TestBed.createComponent(Test); component = fixture.componentInstance; element = fixture.debugElement.query(By.css('div')).nativeElement; fixture.detectChanges(); }); afterEach(() => { fixture.destroy(); }); it('should compile Test', () => { expect(element).toBeTruthy(); }); ¿Por qué la instancia del componente Test no se elimina de DOM y cómo se debe solucionar?
¿Por qué se agregan componentes de accesorios al DOM? ¿Se pueden separar de DOM como $rootElement en AngularJS?
Ni Jasmine ni Angular lo eliminarán automáticamente, tal vez para ayudarlo a obtener más detalles sobre la ejecución de su prueba.
Para eliminarlo, simplemente use afterEach(...) , como:
beforeEach(() => { fixture = TestBed.createComponent(MyComponent); comp = fixture.componentInstance; debugElement = fixture.debugElement; element = debugElement.nativeElement; }); afterEach(() => { document.body.removeChild(element); });Para ninguno de los usuarios de Angular:
afterEach(() => { document.body.innerHTML = ''; });Lo anterior borra todas las etiquetas
<script>predeterminadas, pero eso no importa (porque ya se ejecutaron y Karma nunca actualiza el navegador, al menos no hasta que finalizan todas las pruebas).
Una solución más concisa:
afterEach(() => { element.remove() }); Donde element es fixture.debugElement.nativeElement
Por favor, eche un vistazo a los siguientes problemas:
1) en primer lugar estás llamando
fixture.destroy();en afterEach , por lo que se llama después de la sección. Es decir, en su sección, el accesorio aún no se destruye.
2) ¿por qué código detecta que el elemento todavía está presente en DOM? Desde otro punto de vista: ¿por qué jasmine/browser debería eliminar ese elemento (qué razón debería hacer jasmine/browser)? Podría sugerir los siguientes casos de uso:
2.1) un componente se usa en otro y debe ser creado/destruido por algún cambio. Es decir , ngIf o ngSwitchCase :
<parent-component> <child-component *ngIf="someChangeInComponent1"></child-component> </parent-component>o
<parent-component [ngSwitch]="type"> <child-component *ngSwitchCase="'something'"></child-component> </parent-component>2.2) se cambia el enrutamiento (pero no es un tema para las pruebas unitarias AFAIK)
3) el código actual recibe la referencia al elemento DOM solo una vez. Debería ser algo como:
beforeEach(() => { ... element = ... }); it('...', () => { ... fixture.detectChanges(); element = ... // try to get element again <--------------------- here })4) si está tratando de encontrar errores como ngOnDestroy() está definido pero implementa OnDestroy no se usa, entonces es más un tema para npm run lint que para pruebas unitarias (eche un vistazo a use-life-cycle-interface en tslint. json ). Después de ejecutar npm run lint , solo verá:
Implement lifecycle hook interface OnDestroy for method ngOnDestroy in class ...Es una buena práctica no tener errores no solo para la prueba unitaria sino también para tslint.