我正在测试项目的功能之一,遇到一个奇怪的问题,我不知道如何解决此问题。

jest -v
24.8.0
node -v
v10.14.2


    const action = (fn1, fn2) => {
        fn1('fn1 call 1');

        return fn2('fn2 call 1')
            .then(() => {
                fn1('fn1 call 2');
                console.log('then was called');
            });
    };

    describe('test case', () => {
        it('should pass', () => {
            const fn1 = jest.fn();
            const fn2 = jest.fn()
                .mockResolvedValue(Promise.resolve('test'));

            action(fn1, fn2);

            expect(fn2).toBeCalledWith('fn2 call 1');
            expect(fn1).nthCalledWith(1,'fn1 call 1');
            expect(fn1).nthCalledWith(2,'fn1 call 2');
        })
    });


输出:

  ● test case › should pass

    expect(jest.fn()).nthCalledWith(expected)

    Expected mock function second call to have been called with:
      ["fn1 call 2"]
    But it was not called.

      19 |             expect(fn2).toBeCalledWith('fn2 call 1');
      20 |             expect(fn1).nthCalledWith(1,'fn1 call 1');
    > 21 |             expect(fn1).nthCalledWith(2,'fn1 call 2');
         |                         ^
      22 |         })
      23 |     });
      24 |

      at Object.nthCalledWith (test.js:21:25)

  console.log test.js:7
    then was called


如果我将fn1替换为:
(args) => console.log(args)

我得到这个:

  console.log test.js:13
    fn1 call 1

  console.log test.js:13
    fn1 call 2

  console.log test.js:7
    then was called


因此,可能我使用jest.fn()的方式存在一些错误
有人可以帮我解决这个问题吗?

最佳答案

您收到此错误的原因是action返回一个承诺,而您没有等待该承诺的结果。当第二次调用fn1时,由于此行expect(fn1).nthCalledWith(2, 'fn1 call 2')而导致测试失败,因此出现错误。另外,在Promise.resolve('test')中调用jest.fn().mockResolvedValue();是多余的see doc

要解决此问题,您需要等待action的结果:

describe('test case', () => {
  it('should pass', async () => {
    const fn1 = jest.fn();
    const fn2 = jest.fn()
      .mockResolvedValue('test');

    await action(fn1, fn2);

    expect(fn2)
      .toBeCalledWith('fn2 call 1');
    expect(fn1)
      .nthCalledWith(1, 'fn1 call 1');
    expect(fn1)
      .nthCalledWith(2, 'fn1 call 2');
  });
});


另一种方法:

describe('test case', () => {
  it('should pass', (done) => {
    const fn1 = jest.fn();
    const fn2 = jest.fn()
      .mockResolvedValue(Promise.resolve('test'));

    action(fn1, fn2)
      .then(() => {
        expect(fn2)
          .toBeCalledWith('fn2 call 1');
        expect(fn1)
          .nthCalledWith(1, 'fn1 call 1');
        expect(fn1)
          .nthCalledWith(2, 'fn1 call 2');
        done();
      });
  });
});

09-25 22:30