簡體   English   中英

在等待上下文中模擬帶有笑話的導入函數

[英]Mock imported function with jest in an await context

我們正在基於express創建一個節點應用程序,以從靜態本地文件中讀取並返回文件中的JSON。

這是我們的json-file.js和我們的route方法:

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()res.status()方法中通過?

最后兩個斷言永遠不會通過,因為測試不會等待以下承諾: const file = await readFilePromise(filePath, 'utf8'); 在這種情況下解決或拒絕,因此從不調用res.sendres.status

要修復它, readJsonFileasync ,您應該在測試中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!'));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM