模拟 Node 模块,该模块使用 Node 中的 Jest 进行链式函数调用

6 javascript unit-testing mocking node.js jestjs

请允许我指出,可以在此处找到与此类似的问题,但已接受的答案的解决方案对我不起作用。还有另一个同样的问题,其答案建议直接操作函数的原型,但这同样没有成果。

我正在尝试使用 Jest 来模拟这个名为“sharp”的 NPM 模块。它需要一个图像缓冲区并对其执行图像处理/操作操作。

该模块在我的代码库中的实际实现如下:

const sharp = require('sharp');

module.exports = class ImageProcessingAdapter {
    async processImageWithDefaultConfiguration(buffer, size, options) {
        return await sharp(buffer)
            .resize(size)
            .jpeg(options)
            .toBuffer();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以看到该模块使用链式函数 API,这意味着模拟必须让每个函数返回this

单元测试本身可以在这里找到:

jest.mock('sharp');
const sharp = require('sharp');

const ImageProcessingAdapter = require('./../../adapters/sharp/ImageProcessingAdapter');

test('Should call module functions with correct arguments', async () => {
    // Mock values
    const buffer = Buffer.from('a buffer');
    const size = { width: 10, height: 10 };
    const options = 'options';

    // SUT
    await new ImageProcessingAdapter().processImageWithDefaultConfiguration(buffer, size, options);

    // Assertions
    expect(sharp).toHaveBeenCalledWith(buffer);
    expect(sharp().resize).toHaveBeenCalledWith(size);
    expect(sharp().jpeg).toHaveBeenCalledWith(options);
});
Run Code Online (Sandbox Code Playgroud)

以下是我的嘲笑尝试:

尝试一

// __mocks__/sharp.js
module.exports = jest.genMockFromModule('sharp');
Run Code Online (Sandbox Code Playgroud)

结果

Error: Maximum Call Stack Size Exceeded
Run Code Online (Sandbox Code Playgroud)

尝试二

// __mocks__/sharp.js
module.exports = jest.fn().mockImplementation(() => ({
    resize: jest.fn().mockReturnThis(),
    jpeg: jest.fn().mockReturnThis(),
    toBuffer:jest.fn().mockReturnThis()
}));
Run Code Online (Sandbox Code Playgroud)

结果

Expected mock function to have been called with:
      [{"height": 10, "width": 10}]
But it was not called.
Run Code Online (Sandbox Code Playgroud)

问题

如果您能帮助我弄清楚如何正确模拟此第三方模块,我将不胜感激,以便我可以对模拟的调用方式做出断言。

我尝试过使用sinonproxyquire,但他们似乎也没有完成工作。

再生产

可以在此处找到此问题的单独再现。

谢谢。

Bri*_*ams 7

你的第二次尝试非常接近。

唯一的问题是,每次sharp被调用时,都会返回一个新的模拟对象,并带有 new resizejpegtoBuffer模拟函数......

...这意味着当你resize这样测试时:

expect(sharp().resize).toHaveBeenCalledWith(size);
Run Code Online (Sandbox Code Playgroud)

...您实际上正在测试一个resize尚未调用的全新模拟函数。

要修复它,只需确保sharp始终返回相同的模拟对象:

__mocks__/sharp.js

const result = {
  resize: jest.fn().mockReturnThis(),
  jpeg: jest.fn().mockReturnThis(),
  toBuffer: jest.fn().mockReturnThis()
}

module.exports = jest.fn(() => result);
Run Code Online (Sandbox Code Playgroud)