Angular 4 компонента прибора сохраняется в DOM во время тестов Jasmine
При запуске Jasmine в реальном браузере я заметил, что компонент TestBed
fixture не разрушен в DOM и сохраняется после завершения тестов:
![введите описание изображения здесь]()
Здесь тестируемый компонент:
@Component({
selector: 'test-app',
template: `<div>Test</div>`,
})
class Test {}
И тест (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();
});
Почему экземпляр компонента Test
не удаляется из DOM и как это должно быть исправлено?
Почему компоненты DOM добавляются в DOM? Могут ли они быть отделены от DOM, как $rootElement
в AngularJS?
Ответы
Ответ 1
Я думаю, что Angular не удаляет его автоматически, чтобы помочь вам получить более подробную информацию о выполнении теста. Чтобы удалить его, вы просто используете afterEach:
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
comp = fixture.componentInstance;
debugElement = fixture.debugElement;
element = debugElement.nativeElement;
});
afterEach(() => {
document.body.removeChild(element);
});
Ответ 2
Пожалуйста, взгляните на следующие проблемы:
1) прежде всего вы вызываете
fixture.destroy();
в afterEach, поэтому он вызывается после раздела it. То есть в он блок крепления все еще не разрушен
2) каким кодом вы обнаруживаете, что элемент все еще присутствует в DOM? С другой точки зрения: почему этот элемент должен быть удален жасмином/браузером (какая причина должна сделать жасмин/браузер)? Я мог бы предложить следующие варианты:
2.1) один компонент используется в другом и должен быть создан/уничтожен некоторым изменением. То есть ngIf или ngSwitchCase:
<parent-component>
<child-component *ngIf="someChangeInComponent1"></child-component>
</parent-component>
или
<parent-component [ngSwitch]="type">
<child-component *ngSwitchCase="'something'"></child-component>
</parent-component>
2.2) изменена маршрутизация (но это не предмет для модульных тестов AFAIK)
3) текущий код получает ссылку на элемент DOM только один раз. Должно быть что-то вроде:
beforeEach(() => {
...
element = ...
});
it('...', () => {
...
fixture.detectChanges();
element = ... // try to get element again <--------------------- here
})
4), если вы пытаетесь найти ошибки, такие как ngOnDestroy(), но реализует OnDestroy, он больше не подходит для npm run lint, чем для модульных тестов (ознакомьтесь с интерфейсом использования-жизненного цикла в tslint.json). После запуска npm run lint вы увидите:
Implement lifecycle hook interface OnDestroy for method ngOnDestroy in class ...
Хорошая практика не иметь ошибок не только для unit test, но и для tslint.
Ответ 3
Более сжатое решение:
afterEach(() => {
element.remove()
});