javascript - CommonJS 和 Jest 模拟 - 导出的函数未被模拟
问题描述
我在使用 commonjs 模拟模块中的特定功能时遇到问题
示例模块db.js
function createDefaultProfile(user_id) {
return { version: 1, username: user_id };
}
function updateOrCreateProfile(user_id, profile) {
if (profile && profile.credential_id) return null; //no need to update
if (!profile) profile = createDefaultProfile(user_id);
if (!profile.credential_id) {
//update profile with key
}
module.exports = {createDefaultProfile, updateOrCreateProfile }
示例测试文件尝试 1:
describe("updateOrCreateUser()", () => {
const db = require('../db.js')
it("should call createDefaultProfile() when no profile is provided", () => {
db.createDefaultProfile = jest.fn()
db.updateOrCreateProfile(userID)
expect(db.createDefaultProfile).toHaveBeenCalledTimes(1)
})
})
示例测试文件尝试2:
describe("updateOrCreateUser()", () => {
jest.mock('../db', () => {
// Require the original module to not be mocked...
const originalModule = jest.requireActual('../db');
return {
__esModule: true, // Use it when dealing with esModules
...originalModule,
createDefaultProfile: jest.fn().mockReturnValue('arbitrary value'),
}
})
const db = require('../db.js')
it("should call createDefaultProfile() when no profile is provided", () => {
db.updateOrCreateProfile(userID)
expect(db.createDefaultProfile).toHaveBeenCalledTimes(1)
})
})
两者都返回错误的值,因为永远不会调用模拟模块。在这两种情况下,似乎模拟模块的范围都不正确...
解决方案
在createDefaultProfile
函数内调用的updateOrCreateProfile
函数是原始的,而不是您尝试用jest.fn()
. 试试下面:
db.js
:
function createDefaultProfile(user_id) {
return { version: 1, username: user_id };
}
function updateOrCreateProfile(user_id, profile) {
if (profile && profile.credential_id) return null;
if (!profile) profile = exports.createDefaultProfile(user_id);
if (!profile.credential_id) {
console.log('update profile with key');
}
}
exports.createDefaultProfile = createDefaultProfile;
exports.updateOrCreateProfile = updateOrCreateProfile;
db.test.js
:
describe('63118259', () => {
describe('updateOrCreateUser', () => {
const db = require('./db.js');
it('should call createDefaultProfile() when no profile is provided', () => {
const userID = 1;
const logSpy = jest.spyOn(console, 'log');
db.createDefaultProfile = jest.fn().mockReturnValueOnce({ credential_id: null });
db.updateOrCreateProfile(userID);
expect(db.createDefaultProfile).toHaveBeenCalledTimes(1);
expect(logSpy).toBeCalledWith('update profile with key');
});
});
});
带有覆盖率报告的单元测试结果:
PASS stackoverflow/63118259/db.test.js (10.819s)
63118259
updateOrCreateUser
✓ should call createDefaultProfile() when no profile is provided (26ms)
console.log
update profile with key
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 77.78 | 50 | 50 | 85.71 |
db.js | 77.78 | 50 | 50 | 85.71 | 2
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.367s
推荐阅读
- javascript - 如何在 javascript 中创建一个返回 HTML 元素的函数
- python - 在进行网络抓取项目时,如何修复 python 中的 beautifulsoup 错误?
- c# - 使用用户输入调用类内的对象
- arraylist - 有没有办法使用 Java 8 中的数据流将由特定字符描述的许多多行字符串收集到 Arraylist 中?
- javascript - Django:从视图中返回文件后下载不开始
- javascript - 如何在 JavaScript 中正确实现循环数组
- c# - System.OutOfMemoryException:内存不足
- python - 在python中按字符分隔字符串
- java - 为什么我的循环在第一次迭代后没有打印循环的第一行?
- php - 如何在 PHP 中基于某些分组将 mysql 查询的结果拆分为多个数组?