【问题标题】:mock a toPromise function in jest - got .toPromise is not a function开玩笑地模拟一个 toPromise 函数 - 得到 .toPromise 不是一个函数
【发布时间】:2020-04-21 01:04:37
【问题描述】:

我有一个来自 nestjs/common 的 httpService

我正在使用如下:

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

在我的笑话规范文件(单元测​​试)中。我正在尝试模拟这项服务

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

});

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

【问题讨论】:

    标签: node.js promise jestjs nestjs


    【解决方案1】:

    “A Jar of Clays”解决方案对我不起作用(我得到 mockImplementation is not a function),但这有效:

        const mockPromise = {
            toPromise: () => Promise.resolve(ical)
        }
    
        mockHttpService.get = jest.fn( () => {return mockPromise});
    

    【讨论】:

      【解决方案2】:

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

      如果你有茉莉花,请使用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方法后面的括号。

      【讨论】:

        【解决方案3】:

        返回值httpService.post需要返回一个Observable&lt;AxiosResponse&lt;T&gt;&gt;,其中包含一个属性toPromise,它是一个函数。你的模拟返回一个已解决的承诺,而它需要返回一个假的 Observable。

        Observable 立即返回,因此post 实现可以只返回一个原始值,但toPromise 需要返回一个承诺。

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

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

        【讨论】:

        • 您是否检查过httpService.post 使用的是模拟功能,而不是真正的功能?您可以尝试在 const response = await this.httpService.post(${this.api}/${action}, data).toPromise(); 行之后放置控制台日志,例如console.log(this.httpService.post)
        • 如果你还没有,你需要导入 httpService 模块,并用jest.mock模拟它
        • 你的mockObservable 可能不应该返回承诺
        猜你喜欢
        • 2016-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-06
        • 1970-01-01
        • 2021-02-07
        • 2018-12-07
        相关资源
        最近更新 更多