如何模拟为回调函数接收到的数据(参数),以便可以开玩笑地测试回调函数中的逻辑?(例如 fs.readFile)

Leo*_* Li 1 javascript unit-testing mocking promise jestjs

我有要进行单元测试的功能,例如,它包含:

function foo (file, option) {
    return new Promise((resolve, reject) => fs.readFile(file, option, (err, content) => {
        if (err) return reject(new Error(`Failed to read the file: (${file})`));
        else {
            (...some operations, and that is the point for me to test it...)
            return resolve(...some result...);
        }
    }));
}
Run Code Online (Sandbox Code Playgroud)

就在测试文件的开头,我有:

jest.mock('fs', () => ({
    readFile : jest.fn(),
}));
const fs = require('fs');
Run Code Online (Sandbox Code Playgroud)

测试逻辑类似于:

test('Should get context as string from the template file', async () => {
    const mockContent = '<a>Hello World</a>';
    fs.readFile.mockReturnValue(mockContent);
    const result = (await foo('test', 'utf8')).then(() => 123);
    //
    expect(result).toEqual(123);
});
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试运行测试时,它显示:

- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.`
Run Code Online (Sandbox Code Playgroud)

我知道这是一个问题,因为 Jest 网站未解决承诺;但他们的建议并不是我真正拥有的......我认识到我的问题是由于fs.readFile(...)被返回的模拟函数所取代,undefined因此new Promise永远不会被拒绝/解决(我说得对吗?!)。

我的问题是如何进行这样的单元测试?我真的不想触发一个 I/O 事件,比如在 oder 中使用一个空文件来使它工作......有什么想法吗?!谢谢!

/// 更新: 我认为一个非常明确的问题是我们如何模拟回调函数接收到的数据。在我的示例中,看起来我对它进行了测试,但在我的真实代码中,我真正想要测试的是回调函数的逻辑。

And*_*rle 6

问题在于你嘲笑的方式js.readFilemockReturnValue只是创建一个返回某些内容的函数,但您希望它调用其参数,因此您需要使用mockImplementation自己定义模拟函数

jest.fn().mockImplementation((file, option, cb) => cb(null, mockContent)) 
Run Code Online (Sandbox Code Playgroud)

或者

jest.fn().mockImplementation((file, option, cb) => cb('Some Error', null))
Run Code Online (Sandbox Code Playgroud)