使用Angular在单元测试覆盖率中包含组件模板

时间:2017-09-05 09:12:57

标签: angular jasmine karma-runner code-coverage istanbul

使用Angular 4可以测试Component的模板,例如检查点击按钮是否触发了预期的方法和类似的东西。

但是如何将模板纳入测试范围?默认情况下它们不是(使用Karma + Jasmine + Istanbul的Angular CLI测试)。

2 个答案:

答案 0 :(得分:0)

我认为,您只能测试单击时调用的函数,因为您无需验证是否单击angular即可调用此函数。

但是,如果您想以任何方式对其进行测试,就可以这样做

import { TestBed, async, ComponentFixture } from '@angular/core/testing';

describe('', () => {
  let fixture: ComponentFixture<TestComponent>;
  let component: TestComponent;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ ],
      declarations: [ TestComponent ],
      providers: [  ]
    }).compileComponents().then(() => {
      fixture = TestBed.createComponent(TestComponent);
      component = fixture.componentInstance;
    });
  }));
});

it('should click on button', async(() => {
  spyOn(component, 'onEditButtonClick');

  let button = fixture.debugElement.nativeElement.querySelector('button');
  button.click(); 
// here you can test you code or just check that your function have been called like in the example bellow 

  fixture.whenStable().then(() => {
    expect(component.onEditButtonClick).toHaveBeenCalled();
  });
}));

答案 1 :(得分:0)

您是否有意要测试模板的实际表示形式?然后,您必须完全切换到开玩笑,而不是业力/茉莉花组合。通过开玩笑,您可以在测试中生成模板快照,将其与组件一起推送并在CI测试中进行检查。

例如,假设您有一个main.component,它在SessionService未准备好时显示加载程序,然后在完成时显示路由内容的路由器出口。开玩笑的快照看起来像这样:

exports[`MainComponent renders: default state 1`] = `
<main
  isReady$={[Function BehaviorSubject]}
  sessionService={[Function Object]}
>
  <loader-line
    ng-reflect-active="true"
  />
</main>
`;

exports[`MainComponent session storage is ready renders 1`] = `
<main
  isReady$={[Function BehaviorSubject]}
  sessionService={[Function Object]}
>
  <main>
    <router-outlet />
  </main>
</main>
`;

测试代码如下:

describe('MainComponent', () => {
  let fixture: ComponentFixture<MainComponent>;

  const isReady$ = new BehaviorSubject(false);
  const mockSessionStorage = Mock.all<SessionService>();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MainComponent, MockComponents(LoaderLineComponent)],
      imports: [RouterTestingModule],
      providers: [mockWith(SessionService, mockSessionStorage)],
    })
      .compileComponents();
  }));

  afterAll(() => {
    isReady$.complete();
  });

  beforeEach(() => {
    Mock.extend(mockSessionStorage).with({isReady$});
    fixture = TestBed.createComponent(MainComponent);
    detectChanges(fixture);
  });

  it(`creates instance`, () => expect(fixture.componentInstance).toBeTruthy());

  it(`renders`, () => expect(fixture).toMatchSnapshot(`default state`));

  describe(`session storage is ready`, () => {
    beforeEach(() => {
      isReady$.next(true);
      detectChanges(fixture);
    });

    it(`renders`, () => expect(fixture).toMatchSnapshot());
  });
});

就是这样,不再需要在规范文件代码中查询<loader-line><router-outlet>,只需查看快照即可。

注意:我还使用了ng-mocks,ts-mockery和一些自己的util函数,但是您要寻找的主要内容是expect(fixture).toMatchSnapshot()行,它们是最好的本机。