Angular2 - 测试一个调用内部http服务的函数

thr*_*exx 3 unit-testing typescript angular

我目前正在尝试测试调用http请求服务的函数,然后在订阅部分执行某些操作(调用函数并设置变量).到目前为止,我的方法是调用函数,我认为将自动调用请求服务,因此将执行订阅部分.但是,我觉得这不是这样做的方式,因为它不起作用.

我要测试的功能:

  public trainBot() {
    this.isTraining = true;
    this.requestsService.trainModel(this.botId, false)
      .subscribe(response => {
        this.trainingStatus = this.trainingStatusMapping[response['status']];
        this.pollTrainingStatus();
      });
  }
Run Code Online (Sandbox Code Playgroud)

到目前为止我的测试(这不起作用).

it('should poll the training status', () => {
    spyOn(component, 'pollTrainingStatus').and.callThrough();
    component.trainBot();
    fixture.detectChanges();
    expect(component.pollTrainingStatus).toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)

那么,任何人都可以告诉我如何测试.subscribe中的那部分(...部分?

更新:

正如有人建议我将returnValue和async添加到我的测试中.他们仍然没有工作,但现在看起来像这样:

it('should poll the training status', fakeAsync(() => {
    component.trainBot();
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
    spyOn(component, 'pollTrainingStatus').and.callThrough();
    fixture.detectChanges();
    tick(1);
    expect(service.trainModel).toHaveBeenCalled();
    expect(component.pollTrainingStatus).toHaveBeenCalled();
  }));
Run Code Online (Sandbox Code Playgroud)

错误是一样的

Jas*_*lin 8

首先,您需要在运行方法trainBot()之前创建Spies.这应该可以修复你的测试.

it('should poll the training status', () => {
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
  spyOn(component, 'pollTrainingStatus');

  component.trainBot();

  expect(service.trainModel).toHaveBeenCalled();
  expect(component.pollTrainingStatus).toHaveBeenCalled();
}));
Run Code Online (Sandbox Code Playgroud)

但是,让我们来谈谈您的测试策略.

说实话,你正在测试一个组件,而不是服务,所以你不应该让服务方法调用.

spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
Run Code Online (Sandbox Code Playgroud)

另外,单元测试应该测试尽可能小的东西.你实际上是在这里测试回调,回调应该是一个命名方法而不是匿名箭头函数.然后,您可以在其他测试中测试和验证回调的功能.

public trainBot() {
  this.isTraining = true;
  this.requestsService.trainModel(this.botId, false)
      .subscribe(response => this.onTrainbotSuccess(response));
}

public onTrainbotSuccess(response) {
  this.trainingStatus = this.trainingStatusMapping[response['status']];
  this.pollTrainingStatus();
}
Run Code Online (Sandbox Code Playgroud)

测试中,您可以测试响应方法是否被调用

it('should call service.trainModel', () => {
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

  component.trainBot();

  expect(service.trainModel).toHaveBeenCalled();
});

it('should send success responses to onTrainbotSuccess()', () => {
  spyOn(component, 'onTrainbotSuccess');
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

  component.trainBot();

  expect(component.onTrainbotSuccess).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)

现在我们可以编写测试,具体说明成功回调的作用.

it('should poll the training status', () => {
  spyOn(component, 'pollTrainingStatus');

  component.onTrainbotSuccess({'status': 'training'});

  expect(component.pollTrainingStatus).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)