开玩笑地模拟一个toPromise函数.toPromise不是一个函数

时间:2020-01-02 10:51:48

标签: node.js promise jestjs nestjs

我有一个来自nestjs / common的httpService

我正在使用以下内容:

const response = await this.httpService.post(`${this.api}/${action}`, data).toPromise();

和我的jest spec文件中(单元测试)。我正在尝试嘲笑此服务

   httpServiceMock = {
      post: jest.fn()
    };

it('should start', async () => {

    const serviceResult = await service.start(data);

});

我遇到了这个错误:

TypeError: this.httpService.post(...).toPromise is not a function

我还试图添加一个承诺结果,例如:

 const promise = Promise.resolve('result');
 httpServiceMock.post.mockResolvedValue(promise);

也尝试过:

it('should start', async () => {

    const mockObservable = Promise.resolve({
        toPromise: () => {
          console.log('toPromise called');
        }
      })

    httpServiceMock.post.mockImplementation(() => mockObservable);

    const serviceResult = await service.start();

});

我的问题是我该如何模仿承诺并返回响应或异常

2 个答案:

答案 0 :(得分:0)

返回值httpService.post需要返回一个Observable<AxiosResponse<T>>,它包含一个属性toPromise,它是一个函数。您的模拟返回一个已解决的诺言,而它需要返回一个假的Observable。

Observable立即返回,因此post实现只能返回原始值,但是toPromise需要返回一个Promise。

返回正确的形状对象以消除此错误:

const mockObservable = {
  toPromise: () => Promise.resolve('result')
}
httpServiceMock.post.mockImplementation(() => mockObservable);

答案 1 :(得分:0)

我有一个类似的问题,无法通过接受的答案解决。所以我带来了另一个解决方案,以防它可以帮助其他人。

如果您有茉莉花,请使用 jasmine.createSpyObj()。如果没有,这就是我需要做的:

首先,我实现了一个 jasmine.createSpyObj() 等价物(基于 this answer,稍作修改):

export class TestUtilsService {
  static createSpyObj (baseName:string, methodNames:string[]): SpyObject {
    let obj: any = {};

    for (let i = 0; i < methodNames.length; i++) {
      obj[methodNames[i]] = jest.fn();
    }
    return {[baseName]:()=>obj};
  };
}

export class SpyObject {
  [key: string]: ()=>{[key:string]:jest.Mock} ;
}

然后我在我的单元测试中使用了它:

const spyHttpClient: SpyObject = TestUtilsService.createSpyObj('get',['toPromise']);

将其添加到测试模块提供程序中:

{provide: HttpClient, useValue: spyHttpClient}

最后,模拟 toPromise 实现以返回模拟响应:

const mockedResponse = {...};
spyHttpClient.get().toPromise.mockImplementationOnce(()=>Promise.resolve(mockedResponse));
await service.myRealMethodThatCallsHttpClient();
expect(service.someUpdatedProp).toBeTruthy();

请注意get方法后面的括号。