在Jasmine测试期间,Angular 4 fixture组件在DOM中持久存在

Est*_*ask 26 javascript unit-testing jasmine typescript angular

在实际浏览器中运行Jasmine时,我注意到TestBed夹具组件在DOM中没有被销毁,并且在测试结束后仍然存在:

在此输入图像描述

这是一个经过测试的组件:

@Component({
  selector: 'test-app',
  template: `<div>Test</div>`,
})
class Test {}
Run Code Online (Sandbox Code Playgroud)

和测试(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();
  });
Run Code Online (Sandbox Code Playgroud)

为什么Test不从DOM中删除组件实例以及如何修复它?

为什么夹具组件会添加到DOM中?他们可以像$rootElementAngularJS 一样脱离DOM 吗?

Jul*_*ova 26

我认为Angular不会自动删除它以帮助您获得有关测试执行的更多详细信息.要删除它,您只需使用afterEach:

beforeEach(() => {
  fixture = TestBed.createComponent(MyComponent);
  comp = fixture.componentInstance;
  debugElement = fixture.debugElement;
  element = debugElement.nativeElement;
});

 afterEach(() => {
  document.body.removeChild(element);
});
Run Code Online (Sandbox Code Playgroud)


Dar*_*yne 7

更简洁的解决方案:

afterEach(() => {
  element.remove()
});
Run Code Online (Sandbox Code Playgroud)

哪里elementfixture.debugElement.nativeElement


Haf*_*uss 7

DOM我还经历了测试用例对 进行的更改,如下所示:

let password = fixture.debugElement.query(By.css('input[id=password]')).nativeElement
    password.value = 'somePassword';
Run Code Online (Sandbox Code Playgroud)

坚持其他测试。我能够使用以下afterEach方法解决此问题:

afterEach(() => {
    TestBed.resetTestingModule();
  });
Run Code Online (Sandbox Code Playgroud)


mar*_*bug 5

请看以下问题:

1)首先你打电话

fixture.destroy();
Run Code Online (Sandbox Code Playgroud)

afterEach 中,所以它在部分之后被调用。即在部分夹具仍然没有被破坏

2) 你通过什么代码检测到元素仍然存在于 DOM 中?从另一个角度来看:为什么那个元素应该被 jasmine/browser 删除(什么原因应该让 jasmine/browser )?我可以建议以下用例:

2.1) 一个组件在另一个组件中使用,应该通过一些更改创建/销毁。即ngIfngSwitchCase

<parent-component>
    <child-component *ngIf="someChangeInComponent1"></child-component>
</parent-component>
Run Code Online (Sandbox Code Playgroud)

或者

<parent-component [ngSwitch]="type">
    <child-component *ngSwitchCase="'something'"></child-component>
</parent-component>
Run Code Online (Sandbox Code Playgroud)

2.2) 路由已更改(但它不是单元测试 AFAIK 的主题)

3) 当前代码只接收一次对 DOM 元素的引用。应该是这样的:

beforeEach(() => {
    ...
    element = ...
});

it('...', () => {
    ...
    fixture.detectChanges();
    element = ... // try to get element again <--------------------- here
})
Run Code Online (Sandbox Code Playgroud)

4)如果你正在努力寻找类似的错误ngOnDestroy()的定义,但工具的OnDestroy不使用,那么它更针对对象NPM运行皮棉比单元测试(请看看在使用生命周期的接口tslint。 json )。运行npm run lint 后,您将看到:

Implement lifecycle hook interface OnDestroy for method ngOnDestroy in class ...
Run Code Online (Sandbox Code Playgroud)

不仅对于单元测试而且对于 tslint 都没有错误是一个很好的做法。