3

我们正在将一个 repo 从 sinon 存根转移到 jest,我在这个模拟中遇到了麻烦。我想做的是在第一次调用时调用实际的实现,然后模拟其余的调用。这个函数是递归的,所以我们希望第一次调用调用实际的实现,然后模拟递归调用。

在sinon,它是这样完成的

const stub = sandbox.stub(instance, 'function');
stub
  .onFirstCall()
  .callsFake(stub.wrappedMethod)
  .callsFake((args) => args);

我想做这样的事情,但在 jest spy 或 mock 实例上找不到实际的实现。这根本不可能吗?

const spy = jest.spyOn(instance, 'function');
spy
  .mockImplementationOnce(spy.mock.actual) // ???
  .mockImplementation((args) => args);
4

2 回答 2

3

为什么你不能做类似如下的事情?

const spy = jest.spyOn(instance, 'function');
spy
  .mockImplementationOnce(() => originalInstanceFunction())
  .mockImplementation((args) => args);

这是一个示例实现 - 注意必须存储对原始实例函数的引用

const original = {
    func: (args) => { console.log(`original ${args}`)} 
};


describe('test', () => {
    it('should call original then mock', () => {
        const originalFunction = original.func;
        const spy = jest.spyOn(original, 'func');
        spy.mockImplementationOnce((args) => originalFunction(args))
            .mockImplementation((args) => console.log(`mock ${args}`));
        
        original.func('test-args');
        original.func('test-args');
        expect(spy).toBeCalledTimes(2);
    });
});

输出:

  console.log
    original test-args

      at originalFunction (test.test.js:2:28)

  console.log
    mock test-args

      at Object.spy.mockImplementationOnce.mockImplementation.args (test.test.js:12:42)
于 2020-11-10T15:29:20.940 回答
3

要使用模拟库执行此操作,请使用jest.requireActual(). 复制指南中的示例:

jest.mock('node-fetch');
const fetch = jest.requireActual('node-fetch');

这允许您fetch在正在测试的代码中模拟库,但fetch在测试本身中使用真正的函数。

于 2021-06-15T19:04:52.767 回答