【问题标题】:Angular 4 fixture component persists in DOM during Jasmine tests在 Jasmine 测试期间,Angular 4 夹具组件在 DOM 中持续存在
【发布时间】:2017-09-24 12:48:04
【问题描述】:

在真实浏览器中运行 Jasmine 时,我注意到 TestBed 夹具组件并未在 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 中?它们可以像 AngularJS 中的 $rootElement 那样从 DOM 中分离出来吗?

【问题讨论】:

    标签: javascript unit-testing angular typescript jasmine


    【解决方案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 部分之后被调用。 IE。在 it 部分中,fixture 仍然没有被破坏

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

    2.1) 一个组件用于另一个组件,应该通过一些更改来创建/销毁。 IE。 ngIfngSwitchCase

    <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() 已定义但未使用 implements OnDestroy 之类的错误,则它更像是 npm run lint 的主题 而不是单元测试(请查看 tslint.json 中的 use-life-cycle-interface)。运行 npm run lint 后,您会看到:

    Implement lifecycle hook interface OnDestroy for method ngOnDestroy in class ...
    

    不仅单元测试没有错误,tslint 也没有错误是一个好习惯。

    【讨论】:

    • 您通过什么代码检测到该元素仍然存在于 DOM 中 - 我自己的眼睛。您可以在问题中发布的 plunk 中看到这一点。 什么理由应该制作 jasmine/浏览器 - 因为我们可以。这是 Jasmine 的核心功能之一。 Angular 无缘无故毁掉了这份报告。我想知道为什么会这样,考虑到 AngularJS 没问题。我相信 OP 结尾的问题已经足够具体了。
    • @estus 这可能是某种回归。需要更多调查。以下网址可能会让您感兴趣:github.com/angular/angular/issues/8458
    • 谢谢。好像很久以前就修好了。我认为这与 TestBed 的工作方式有关,并且可能这就是它默认的工作方式。只是不知道为什么,如果可能的话如何改变。
    【解决方案3】:

    更简洁的解决方案:

    afterEach(() => {
      element.remove()
    });
    

    elementfixture.debugElement.nativeElement

    【讨论】:

      【解决方案4】:

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

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

      在其他测试中持续存在。我可以通过使用以下afterEach 方法解决此问题:

      afterEach(() => {
          TestBed.resetTestingModule();
        });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-24
        • 2011-12-02
        • 1970-01-01
        • 2023-04-02
        • 2015-02-27
        • 2015-04-22
        • 1970-01-01
        • 2017-11-18
        相关资源
        最近更新 更多