Jest 单元测试函数调用第二个返回承诺的函数

时间:2021-04-30 10:27:51

标签: javascript typescript unit-testing testing jestjs

已应用 vazsonyidl 建议的编辑问题

我必须为与此类似的函数编写单元测试:

import {External} from 'ExternalModule';

async functionA(){
    this.functionB().then((data) => {
        External.functionC(options);
        console.log("Reached1");

    }).catch((data) => {
        const { OnError = "" } = data || {}
        if(OnError) {
            External.functionC(anotherOptions);
            console.log("Reached2");
        }
    })
}

functionB() {
    return new Promise(() => {
    });
  }

由于 functionC 属于另一个模块,我在 _mocks_ 文件夹中放置了一个它的模拟:

//_mocks_/ExternalModule.ts

export var External: ExternalClass = {
  functionC(){}
}

class ExternalClass{
  constructor(){};
  functionC(){};
}

我用两种不同的方式模拟了 functionB 来测试 thencatch :

it("should test then block", () => {
        functionB = jest.fn(() => {return Promise.resolve()});

        const functionSpy = jest.spyOn(ExternalModule.External, 'functionC');
        void functionA().then(() => {
          expect(functionSpy).not.toHaveBeenCalled();
        });
    })

it("should test catch block", () => {
        const err = { OnError: "Error" };
        functionB = jest.fn(() => {return Promise.reject(err)});

        const functionSpy = jest.spyOn(ExternalModule.External, 'functionC');
        void functionA().then(() => {
          expect(functionSpy).not.toHaveBeenCalled();
        });
    })

我想要做的是期望 functionC 被调用并使用正确的参数调用,但即使我测试 functionC 是否未被调用,测试也总是通过。

我做错了什么?

3 个答案:

答案 0 :(得分:0)

我认为当这个函数捕捉到错误时,这个错误应该有一个“OnError”属性,这样 functionC 才能运行。

const { OnError = "" } = data || {}
if(OnError) {
    ExternalClass.functionC(anotherOptions);
}

将您的响应错误数据更改为 return Promise.reject({OnError: '404'}) 可能会解决此问题。

答案 1 :(得分:0)

因为你没有把它提供给你的班级。 以下代码对我有用:

class A {
  async functionA() {
    this.functionB().then((data) => {
      this.functionC(); // It woll log aaa here, you need this one.
    }).catch((data) => {
      const {OnError = ''} = data || {};
      if (OnError) {
        console.log('onerror');
      }
    });
  }

  functionB() {
    return new Promise(() => {
    });
  }

  functionC() {
    return 2;
  }
}

describe('a', () => {
  it('test',  () => {
    const a = new A();
    a.functionB = jest.fn(() => Promise.resolve());
    const functionBSpy = jest.spyOn(a, 'functionC');
    void a.functionA().then(() => {
      expect(functionBSpy).toHaveBeenCalledTimes(1);
    });
  });
});

希望这会有所帮助,感谢任何评论。

由于您没有提供有关您的函数 B 的信息,我嘲笑了一些可能适合您的内容

您最初的问题是 Jest 不会等待您的回调解决。它执行断言,尽管即使您的函数调用稍后发生,Jest 也不会识别它们并说从未发生过调用。

有几个可用的文档,例如 Jest 的一个 here

答案 2 :(得分:0)

Jest 在执行断言之前不会等待异步代码完成。

您可以使用以下功能:

const waitForPromises = () => new Promise(setImmediate);

强制 Jest 在继续之前等待承诺完成:


it("does something", async () => {
  promiseCall();
  await waitForPromises();
  expect(something).toBe(something)
});