[英]Jest mock nested function from another file
我正在學習 NodeJs 和 Jest。 我在進行單元測試時遇到了麻煩。 我只是將我的實際代碼翻譯成一個簡單的邏輯。 我有兩個文件如下。
// age.js
function getAge(birthYear) {
const age = 2021-birthYear;
return age
}
module.exports = { getAge }
// user.js
const { getAge } = require("./age");
async function isMinor(){
const bYear = 1991
const age = await getAge(bYear)
if( age <= 18) {
return true
}
return false
}
module.exports = { isMinor }
isMinor
從另一個文件調用getAge
,我想測試isMinor
而不實際調用getAge
。 我參考了這篇文章並寫了我的測試,但我仍然遇到了一些問題。
// user.test.js
const { isMinor } = require("./user")
describe("Age Test", () => {
// Question 1: how can I properly import getAge function here and mock a return value for it? I also tried mockImplementation and mockReturnedValue, but they didn't work
// I don't want to actually invoke getAge function
beforeEach(() => {
jest.mock("./age", () => ({
getAge: () => 99,
}))
})
// Question 2: How can I teardown the moch after the test
afterEach(() =>{
getAge.mockRestore()
})
test("should be an adult", async () => {
const isMinor = await isMinor();
expect(isMinor).toEqual(false);
});
});
我希望從getAge
收到 99 ,但它返回null
。 我很感激任何幫助。 謝謝你。
下面的示例使用"jest": "^26.6.3"
。
user.js
:
const { getAge } = require('./age');
async function isMinor() {
const bYear = 1991;
const age = await getAge(bYear);
console.log('age: ', age);
if (age <= 18) {
return true;
}
return false;
}
module.exports = { isMinor };
選項 1 :在beforeEach
鈎子功能 scope 中使用jest.mock()
,它不會被提升到代碼的頂部。 所以你需要通過jest.mock()
方法在 mocking 之后需要模塊。
describe('Age Test', () => {
beforeEach(() => {
jest.mock('./age', () => ({
getAge: jest.fn(() => 99),
}));
});
test('should be an adult', async () => {
const { isMinor } = require('./user');
const { getAge } = require('./age');
const actual = await isMinor();
expect(actual).toBeFalsy();
expect(getAge).toBeCalledWith(1991);
});
});
單元測試結果:
PASS examples/66288290/user.test.js
Age Test
✓ should be an adult (1911 ms)
console.log
age: 99
at examples/66288290/user.js:6:11
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 87.5 | 50 | 100 | 87.5 |
user.js | 87.5 | 50 | 100 | 87.5 | 8
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.197 s
選項 2 :在模塊 scope 中使用jest.mock()
,它將被提升到代碼的頂部。 即使您require
文件頂部的模塊。 您需要的./age
模塊已經被模擬了。
const { isMinor } = require('./user');
const { getAge } = require('./age');
jest.mock('./age', () => ({
getAge: jest.fn(() => 99),
}));
describe('Age Test', () => {
afterAll(() => {
jest.resetAllMocks();
});
test('should be an adult', async () => {
const actual = await isMinor();
expect(actual).toBeFalsy();
expect(getAge).toBeCalledWith(1991);
});
});
單元測試結果:
PASS examples/66288290/user.test.js
Age Test
✓ should be an adult (11 ms)
console.log
age: 99
at examples/66288290/user.js:6:11
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 87.5 | 50 | 100 | 87.5 |
user.js | 87.5 | 50 | 100 | 87.5 | 8
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.502 s
由於您僅使用模擬值測試isMinor
,因此您需要使用多個值對其進行測試以涵蓋所有不同的場景(分支),因此您只需調用一次即可為./age.js
創建一次模擬:
const { getAge } = require('./age');
jest.mock('./age');
它將為每個模塊 function 生成一個模擬 function 僅用於此測試文件
使用 jest.mock 模擬的模塊僅對調用 jest.mock 的文件進行模擬。 另一個導入模塊的文件將獲得原始實現,即使它在模擬模塊的測試文件之后運行。
因此,您無需恢復原始實現。
使用自動模擬的最大優勢是當實現中的方法(在本例中為getAge
)被刪除時 - 測試將失敗。
剩下要做的就是設置要測試的模擬的返回值。 並且由於預計會返回 promise 您應該使用.mockResolvedValue()
user.test.js
const { isMinor } = require("./user");
const { getAge } = require('./age');
jest.mock('./age');
describe("Age Test", () => {
describe('getAge returning more than 18', () => {
beforeAll(() => {
getAge.mockResolvedValue(99)
})
test("should be an adult", async () => {
expect(await isMinor()).toEqual(false);
});
})
describe('getAge returning less than 18', () => {
beforeAll(() => {
getAge.mockResolvedValue(13)
})
test("should be a minor", async () => {
expect(await isMinor()).toEqual(true);
});
})
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.