如何使用@Input和类型Observable测试组件

时间:2018-09-28 19:00:36

标签: angular unit-testing jasmine karma-jasmine

我对于为Angular编写单元测试并不陌生,无法弄清楚如何使用@Input指令为组件编写单元测试。

这是我的

== file.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-bugs-table',
  templateUrl: './bugs-table.component.html',
  styleUrls: ['./bugs-table.component.scss']
})
export class BugsTableComponent implements OnInit {
//   priorityData: any = [];
  @Input() bugsDataService;
  @Input() gridItemComponent;
  constructor(
  ) {  }

  ngOnInit() {

  }
    ngAfterViewInit() {
this.bugsDataService.subscribe(response => {
  this.bugsData = response;
})

}     }

这是我的file.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule, } from '@angular/forms';
import { HttpModule, BrowserXhr } from "@angular/http";

fdescribe('BugsTableComponent', () => {
  let component: BugsTableComponent;
  let fixture: ComponentFixture<BugsTableComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ BugsTableComponent ],
      imports: []
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(BugsTableComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  fit('should create', () => {
    expect(component).toBeTruthy();
  });
});

但是失败并显示错误:

  

×应该创建         无头Chrome 69.0.3497(Windows 10.0.0)       TypeError:无法读取未定义的属性“ subscribe”

我知道这是因为bugsDataService(可观察到的)未定义。 任何可以帮忙解决此问题。 如果需要更多信息,请告诉我。

2 个答案:

答案 0 :(得分:1)

以下作品:

包括此导入:

import { of } from 'rxjs';

将文件的beforeEach块更改为:

beforeEach(() => {
  fixture = TestBed.createComponent(BugsTableComponent);
  component = fixture.componentInstance;

  // needed because ngAfterViewInit gets called and if there isn't an observable to subscribe to it will fail
  component.bugsDataService = of(null);

  fixture.detectChanges();
});

编写测试:

it('Should assign the input value to bugsdata', () => {
  // Arrange
  component.bugsData = {}; // to make sure it's empty at the start
  const resultFromService = {hello: 'world'};
  component.bugsDataService = of(resultFromService); // this creates an observable from resultFromService

  // Act
  component.ngAfterViewInit();

  // Assert
  expect(component.bugsData).toEqual(resultFromService);
});

一些注意事项:

  • 我注意到您的组件有一个ngAfterViewInit,但是该类没有实现它。如果您不使用ngOnInit,则在类声明中将其替换为ngAfterViewInit并更新导入。
  • 如果您不想执行我在beforeEach块中建议的更改,则可以将预订行从ngAfterViewInit移动到ngAfterViewInit所调用的单独方法。但是,您随后需要对其进行监视,以使其实际上不会被调用。

答案 1 :(得分:0)

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ BugsTableComponent ],
      imports: [],
      providers: [BugsDataService] // inject service here 
    })
    .compileComponents();
  }));

这应该可以修复错误,但

如果要模拟服务的实际行为,更好的方法是创建一个扩展BugsDataService的模拟服务,并在单元测试用例中使用它来提供模拟数据

示例

@Injectable()
export class BugsDataMockService extends BugsDataService {

overridenMethod() {
return Observable.of( { data : yourmockresponse });
}


And in your Spec file (Unit test)
beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ BugsTableComponent ],
      imports: [],
      providers: [ { provide: BugsDataService, useClass: BugsMockDataService } ] // Use Mock Service instead of original one 
    })
    .compileComponents();
  }));