我们正在基于express创建一个节点应用程序,以从静态本地文件中读取并返回文件中的JSON。
以下是我们的json-file.js
和我们的路线方法:
const readFilePromise = require('fs-readfile-promise');
module.exports = {
readJsonFile: async (req, res) => {
try {
const filePath = 'somefile.json';
const file = await readFilePromise(filePath, 'utf8');
res.send(file);
} catch(e) {
res.status(500).json(e);
}
},
};
我们使用第三方模块fs-readfile-promise
,该模块基本上将节点readFileSync
变成了承诺。
但是我们很难模拟这个第三方的实现,以便能够产生两个测试:一个基于模拟读取文件(已解决承诺),另一个基于拒绝。
这是我们的测试文件:
const { readJsonFile } = require('../routes/json-file');
const readFilePromise = require('fs-readfile-promise');
jest.mock('fs-readfile-promise');
const resJson = jest.fn();
const resStatus = jest.fn();
const resSend = jest.fn();
const res = {
send: resSend,
status: resStatus,
json: resJson,
};
resJson.mockImplementation(() => res);
resStatus.mockImplementation(() => res);
resSend.mockImplementation(() => res);
describe('json routes', () => {
beforeEach(() => {
resStatus.mockClear();
resJson.mockClear();
resSend.mockClear();
});
describe('when there is an error reading file', () => {
beforeEach(() => {
readFilePromise.mockImplementation(() => Promise.reject('some error'));
});
it('should return given error', () => {
readJsonFile(null, res);
expect(readFilePromise).lastCalledWith('somefile.json', 'utf8'); // PASS
expect(resStatus).lastCalledWith(500); // FAIL : never called
expect(resSend).lastCalledWith({ "any": "value" }); // FAIL : never called
});
});
});
我们试图将readFilePromise.mockImplementation(() => Promise.reject('some error'));
放在顶部,紧随jest.mock()
之后。
第三方代码基本上类似于:
module.exports = async function fsReadFilePromise(...args) {
return new Promise(....);
}
我们如何模拟和替换模块的实现,以根据测试设置返回Promise.resolve()
或Promise.reject()
,以使测试用例在res.send()
或{{1}中通过}方法?
答案 0 :(得分:2)
最后2个断言不会通过,因为测试不会等待const file = await readFilePromise(filePath, 'utf8');
中的诺言在这种情况下解决或拒绝,因此永远不会调用res.send
或res.status
。
要解决此问题,readJsonFile
是async
,则应在测试中await
:
it('should return given error', async () => {
await readJsonFile(null, res);
...
})
我们如何模拟和替换模块的实现以返回 Promise.resolve()或Promise.reject()取决于我们的测试 设置以使我们的测试用例在res.send()或res.status()中通过 方法
确切的操作方式:
readFilePromise.mockImplementation(() => Promise.reject('some error'));
或
readFilePromise.mockImplementation(() => Promise.resolve('SomeFileContent!'));