Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 在单元测试覆盖率中包含组件模板_Angular_Jasmine_Karma Runner_Code Coverage_Istanbul - Fatal编程技术网

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

Angular 在单元测试覆盖率中包含组件模板,angular,jasmine,karma-runner,code-coverage,istanbul,Angular,Jasmine,Karma Runner,Code Coverage,Istanbul,使用Angular 4可以测试组件的模板,例如检查单击按钮是否触发预期的方法等 但是,如何将模板包括在测试覆盖范围内呢?默认情况下,它们不是(使用带有Karma+Jasmine+Istanbul的Angular CLI测试)。在我看来,您只能在单击时测试调用的函数,因为您不需要验证单击Angular是否会调用此函数 但是如果你想用任何方法测试它,你可以这样做 import { TestBed, async, ComponentFixture } from '@angular/core/testi

使用Angular 4可以测试组件的模板,例如检查单击按钮是否触发预期的方法等


但是,如何将模板包括在测试覆盖范围内呢?默认情况下,它们不是(使用带有Karma+Jasmine+Istanbul的Angular CLI测试)。

在我看来,您只能在单击时测试调用的函数,因为您不需要验证单击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();
  });
}));
从'@angular/core/testing'导入{TestBed,async,ComponentFixture};
描述(“”,()=>{
let夹具:组件夹具;
let组件:TestComponent;
beforeach(异步(()=>{
TestBed.configureTestingModule({
进口:[],
声明:[TestComponent],
提供者:[]
}).compileComponents()。然后(()=>{
fixture=TestBed.createComponent(TestComponent);
组件=fixture.componentInstance;
});
}));
});
它('应该点击按钮'),异步(()=>{
spyOn(组件“onEditButtonClick”);
let button=fixture.debugElement.nativeElement.querySelector('button');
按钮。单击();
//在这里,您可以测试您的代码,或者检查您的函数是否已被调用,如下面的示例所示
fixture.whenStable()然后(()=>{
expect(component.onEditButtonClick).toHaveBeenCalled();
});
}));

您的意思是想测试模板的实际表示形式吗?然后,你必须完全转向玩笑,而不是因果报应/茉莉花组合。使用jest,您可以在测试中生成模板快照,这些快照与组件一起推送,并在CI测试中检查

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

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>
`;
exports[`MainComponent呈现:默认状态1`]=`
`;
导出[`MainComponent会话存储已就绪渲染1`]=`
`;
测试代码如下所示:

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());
  });
});
description('MainComponent',()=>{
let夹具:组件夹具;
const isReady$=新行为主体(false);
const mockSessionStorage=Mock.all();
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[MainComponent,MockComponents(LoaderLineComponent)],
导入:[RouterTestingModule],
提供者:[mockWith(会话服务,mockSessionStorage)],
})
.compileComponents();
}));
毕竟(()=>{
isReady$.complete();
});
在每个之前(()=>{
extend(mockSessionStorage).with({isReady$});
fixture=TestBed.createComponent(主组件);
检测变化(夹具);
});
它(`creates instance`,()=>expect(fixture.componentInstance.toBeTruthy());
它(`renders`,()=>expect(fixture.toMatchSnapshot(`defaultstate`));
描述(`session storage is ready`,()=>{
在每个之前(()=>{
isReady$.next(true);
检测变化(夹具);
});
它(`renders`,()=>expect(fixture.toMatchSnapshot());
});
});
就这样,不再查询规范文件代码中的
,只需查看快照即可


注意:我也在使用ng mocks、ts mockry和一些自己的util函数,但是您要寻找的主要内容是
expect(fixture).toMatchSnapshot()
行,它们是本机的笑话。

在我看来,您应该重新思考您想要测试什么以及如何测试。您可以测试是否从组件内部触发了某些内容(单元测试),例如,如果我调用此函数,则此属性会更改值

导出类页面{
列表内容:字符串[]=[];
addStuff:(item:string)=>this.listOfSomething.push(item);
}
在这里,您可以测试某物的
列表是否随时间而变化

若要知道某个按钮是否从模板中的
按钮执行此操作,则可能会出现这种情况

{{item}
添加内容
在这种情况下,如果单击按钮,您希望看到屏幕上的元素数量发生变化。基本上,您是在间接地检查
addStuff
list of something
,但仍然在检查它们

--

总之,您需要将测试分为单元测试和e2e测试。 Jasmine更适合于单元测试。你可能会找到一种方法,但不值得花时间

下面您可以看到登录页面(e2e)所需的不同方法

从“量角器”导入{browser,by,element};
导出常量testData={
用户名:1231232,
密码:“pass1234”
};
导出类登录页{
//////////////////////////////////////////////////////////////////////////////////////////
//导航//////
导航(){
返回browser.get('/login');
}
快速登录(){
这是navigateTo();
this.setMobileNumber(testData.userName);
this.setPassword(testData.password);
这是doLogin();
}
//////////////////////////////////////////////////////////////////////////////////////////
//选择器/////
getLoginButton(){
返回元素(by.buttonText(“登录”);
}
//////////////////////////////////////////////////////////////////////////////////////////
//getText///////
GetSelectedMobileNumber前缀(){
返回元素(by.deepCss('section form.mat select.value output')).getText();
}
getErrorMessage(){
return元素(by.deepCss('snack-bar-container-simple snack-bar span')).getText();
}
//////////////////////////////////////////////////////////////////////////////////////////
//发送键//////
setMobileNumber(电话号码:number){
返回元素(by.css('[formControlName=phoneNumber]')).sendKeys(phoneNumber);
}
设置密码(密码:字符串){
返回元素(按.css('[formControlName=pass