angular2单元测试:无法读取componentInstance.method()的属性未定义

Dae*_*esi 5 unit-testing jasmine typescript karma-jasmine angular

mycomponent.spec.ts类:

这将引发错误:无法读取未定义的属性'ngOnInit'。

let myComponent: MyComponent;
let myService: MyService;

describe('myComponent', () => {
   beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
    providers: [
      {provide: MyService, useClass: MockMyService} // **--passing Mock service**
  ]
}).compileComponents()
  .then(() => {
    myComponent = TestBed.createComponent(MyComponent).componentInstance;
    myService = TestBed.get(MyService);
    console.log(myService.getData());
  });
});

it('should get the mock data', () => {
   myComponent.ngOnInit(); //-----------> seems like myComponent is not defined at this place, how to resolve this error 
   expect(myComponent.data).toBe(DATA_OBJECT);
  });
});
Run Code Online (Sandbox Code Playgroud)

以下是MyComponent:

@Component({
  selector: 'pm-catalogs',
  templateUrl: './catalog-list.component.html'
})

export class MyComponent implements OnInit {

 public data: IData[];

 constructor(private _myService: MyService) {

}

public ngOnInit(): void {
this._myService.getData()
  .subscribe(
    data => this.data = data
  //  error => this.errorMessage = <any>error
  );
 }
}
Run Code Online (Sandbox Code Playgroud)

下面是模拟服务

  export const DATA_OBJECT: IData[] = [
 {
   'Id': 1,
   'value': 'abc'
 },
 {
'Id': 2,
'value': 'xyz'
 }];

@Injectable()
export class MockMyService {
 public getData(): Observable<IData[]> {
    return Observable.of(DATA_OBJECT);
  }
}
Run Code Online (Sandbox Code Playgroud)

我是Angular2测试的新手,当myComponent.ngOnInit()调用我的规范类中的myService.getData()方法时,我希望myService.getData返回DATA_OBJECT,请帮助我实现这一点。

Est*_*ask 6

问题是异步beforeEach实现不正确,这会导致竞争条件。

.compileComponents().then(() => { ... })beforeEach块导致在延迟代码执行then回调至少为一个刻度。itmyComponent在有机会被分配之前从不等待并访问变量。

当测试没有失败时,这种竞争条件会变得不那么明显和更危险。相反,当beforeEach以前的测试影响当前测试中的变量时,测试可能会受到交叉污染。

.compileComponents()是同步的,除非有带有styleUrls和的组件templateUrl(就像上面的例子)。在这种情况下,它变成异步的,async应该使用 helper:

// asynchronous block
beforeEach(async(() => {    
  TestBed.configureTestingModule({ ... })
  .compileComponents();
}));

// synchronous block
beforeEach(() => {    
  myComponent = ...
});
Run Code Online (Sandbox Code Playgroud)

根据经验,如果块有可能是异步的,块应该用asyncof fakeAsynchelper包装。

当使用 测试组件类时TestBed,它们遵循一个生命周期并自动调用它们的钩子。ngOnInit()不需要手动调用(正如另一个答案所解释的那样)并且会导致两次调用挂钩。