开玩笑:child_process.exec.mockImplentation 不是一个函数

mad*_*die 2 unit-testing child-process node.js jestjs

我有一个使用该child_process.exec函数的函数:

//serverUtils.js:
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);

  async getUpstreamRepo() {
    try {
      const forkConfig = (await exec('git remote get-url upstream')).stdout;
      let upstreamRepo = forkConfig.replace('git@github.com:', '');
      upstreamRepo = upstreamRepo.replace(/\r?\n|\r/g, '');
      return upstreamRepo;
    } catch (error) {
      console.error(error);
      throw error;
    }
  },
Run Code Online (Sandbox Code Playgroud)

看完这篇 SO post 后,我​​尝试像这样模拟 exec 调用:

//serverUtils.test.js:
const child_process = require('child_process');
jest.mock('child_process')
describe('Test Class', () => {
    ....
    it('check upstream repo', async () => {      

    child_process.exec.mockImplentation(jest.fn().
        mockReturnValueOnce('git@github.com:mock/url.git'))

    await expect(serverScript.getUpstreamRepo()).
        resolves.toEqual('mock/url.git');
    });
 }
Run Code Online (Sandbox Code Playgroud)

然而,child_process.exec.mockImplentation is not a function 正如链接的帖子所解释的那样,“ Jest 文档说,当模拟 Node 的核心模块时,需要调用 jest.mock('child_process') 。” ——我显然是这么做的。

mga*_*cia 5

您看到的错误是因为您正在调用mockImplentation而不是mockImplementation. 不幸的是,当您纠正该拼写错误时,测试仍然无法通过。

这是因为您正在调用promisify方法exec,允许将其用作承诺。promisify底层的作用是从基于异步回调的函数(其中回调放置在最后一个参数,并以错误作为第一个参数和数据作为第二个参数来调用)转换为基于承诺的函数。

因此,为了使该promisify方法正常工作,您必须模拟该exec方法,以便它调用回调参数,以便解决承诺。

另请注意,您正在stdout从调用结果中读取参数exec,因此在返回的数据中,您必须发送具有该属性的对象。

考虑到所有这些:

it('check upstream repo', async () => {
    child_process.exec.mockImplementation((command, callback) => {
        callback(null, { stdout: 'git@github.com:mock/url.git' });
    });

    await expect(serverScript.getUpstreamRepo()).
        resolves.toEqual('mock/url.git');
});
Run Code Online (Sandbox Code Playgroud)

另一个可能的解决方案是直接模拟该promisify方法:

jest.mock('util', () => ({
    promisify: jest.fn(() => {
        return jest.fn().mockResolvedValue({ stdout: 'git@github.com:mock/url.git' });
    })
}));

describe('Test Class', () => {
    it('check upstream repo', async () => {
        await expect(serverScript.getUpstreamRepo()).
            resolves.toEqual('mock/url.git');
    });
});
Run Code Online (Sandbox Code Playgroud)