如何在Jest中正确模拟fs.readFileSync()



我正在使用fs模块将一个html字符串导入到我的模块中,如下所示:

const fs = require('fs');    
const htmlString = fs.readFileSync("../utils/htmlString.html").toString();

然后,在我的测试文件中,我试图模拟fs模块,如下所示:

const fs = require('fs');
jest.mock("fs", () => {
return {
readFileSync: jest.fn()
}
})
fs.readFileSync.mockReturnValue("test string");

我可能错误的逻辑告诉我,它应该正确地模仿原始字符串导入,并将其替换为";测试串";一串然而,在运行测试时,它抛出:

TypeError:无法读取未定义的属性"toString">

我知道这意味着mock不成功,因为它应该在字符串实例上成功调用.toString((。

我在这里做错了什么?

您不需要为jest.mock('fs')显式提供模块工厂参数。jest.mock()在需要时使用自动模拟版本模拟模块。这意味着fs.readFileSync是一个与jest.fn()相同的mock方法。

您需要确保在模拟返回值后需要测试中的模块,因为模块范围内的代码将在需要时立即执行。

例如

index.js:

const fs = require('fs');
const htmlString = fs.readFileSync('../utils/htmlString.html').toString();
console.log('htmlString: ', htmlString);

index.test.js:

const fs = require('fs');
jest.mock('fs');
describe('70760704', () => {
test('should pass', () => {
expect(jest.isMockFunction(fs.readFileSync)).toBeTruthy();
fs.readFileSync.mockReturnValue('test string');
require('./');
});
});

测试结果:

PASS  stackoverflow/70760704/index.test.js (7.242 s)
70760704
✓ should pass (14 ms)
console.log
htmlString:  test string
at Object.<anonymous> (stackoverflow/70760704/index.js:3:9)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        7.279 s, estimated 8 s

jest.config.js:

module.exports = {
testEnvironment: 'node',
};

软件包版本:

"jest": "^26.6.3"

我的一个函数调用fs.readFileSync,所以我想存根readFileSync,这样它就会在我的一次Jest测试中抛出错误。以下是我所做的:

utils.ts:

import { readFileSync } from 'fs';
export const myFunc() {
...
try {
data = readFileSync("path/to/file.json", { encoding: 'utf-8' });
} catch (e) {
console.warn("Error", e);
return undefined;
}
...
}

utils.test.ts:

import { myFunc } from 'lib/utils'
import * as fs from "fs"; // or const fs = require("fs");
test("my test", () => {
jest.spyOn(fs, "readFileSync").mockImplementationOnce(func => {
throw new Error("Mock file read error.");
});
const retVal = myFunc();
expect(retVal).toBeUndefined();
});

最新更新