Jest - 模拟从被测函数调用的函数

时间:2021-04-21 04:05:27

标签: javascript node.js unit-testing jestjs mocking

我有一个 utils.js 文件,其中的函数调用同一文件中的另一个函数。像这样:

// utils.js    
async function originalFunc (params) {
    ...

    await anotherFunc(arg1, arg2)
}

在另一个文件中,我使用 jest 来测试 originalFunc

// utils.test.js
test('should test orginalFunc', async () => {
    const params = {
        arg1: 'data1',
        arg2: 'data2',
    }

    const anotherFunc = jest.fn()

    await util.originalFunc(params)

    // todo: expect anotherFunc to be called with correct params
})

但是,当使用此配置时,将调用真正的 anotherFunc 而不是模拟 jest.fn() 版本。

我也试过像这样模拟模块:

jest.mock('../src/util', () => ({
    ...jest.requireActual('../src/util'),
    anotherFunc: jest.fn(),
}));

但这也行不通。

如何强制 originalFunc 使用 anotherFunc 的模拟实现?

1 个答案:

答案 0 :(得分:0)

使用 anotherFunc 保持对 exports.anotherFunc 函数的相同引用。然后,您可以使用 jest.spyOn() 来模拟它。

例如

utils.js

async function originalFunc(params) {
  await exports.anotherFunc(params.arg1, params.arg2);
}

async function anotherFunc(arg1, arg2) {
  console.log('real anotherFunc implementation');
}

exports.originalFunc = originalFunc;
exports.anotherFunc = anotherFunc;

utils.test.js

const utils = require('./utils');

describe('67189137', () => {
  it('should pass', async () => {
    const params = {
      arg1: 'data1',
      arg2: 'data2',
    };
    const anotherFuncSpy = jest
      .spyOn(utils, 'anotherFunc')
      .mockImplementation(() => console.log('mock anotherFunc implementation'));
    await utils.originalFunc(params);
    expect(anotherFuncSpy).toBeCalledWith('data1', 'data2');
  });
});

单元测试结果:

 PASS  examples/67189137/utils.test.js (8.324 s)
  67189137
    ✓ should pass (20 ms)

  console.log
    mock anotherFunc implementation

      at Object.<anonymous> (examples/67189137/utils.test.js:11:41)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.347 s

另一种方法是使用依赖注入,将 anotherFunc 作为参数传递给 originalFunc 函数,如下所示:

async function originalFunc(params, anotherFunc) {
  await anotherFunc(params.arg1, params.arg2);
}