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

时间:2017-08-02 19:15:22

标签: angular unit-testing typescript

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

我想测试的功能:

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

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

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

那么,任何人都可以告诉我如何在.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();
  }));

错误是相同的

2 个答案:

答案 0 :(得分:6)

首先,您需要在运行方法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();
}));

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

说实话,您正在测试组件,而不是服务,所以您不应该让服务方法通过。

spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

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

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();
}

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

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();
});

现在我们可以针对成功回调的具体内容编写测试。

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

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

  expect(component.pollTrainingStatus).toHaveBeenCalled();
});

答案 1 :(得分:0)

传递给subscribe()的函数是异步调用的。这意味着您的断言在调用this.pollTrainingStatus()之前运行。您需要使用async() or fakeAsync() utility function

在代码中可以看起来像这样(如果使用fakeAsync()):

import { fakeAsync } from '@angular/core/testing';

it('should poll the training status', fakeAsync(() => {
  ...
  expect(component.pollTrainingStatus).toHaveBeenCalled();
}));