如何在Jest中mock被测服务依赖的storageConnectionString常量?
问题描述
我正在测试名为connect-key.js的文件,该文件依赖keyvault-emulator模块。相关文件代码如下:
文件1:connect-key.js
// connect-key.js file const { save, retrieve, init } = require('./keyvault-emulator') .... .... .... // SOME TESTS
文件2:keyvault-emulator.js
// The keyvault-emulator.js file const { storageConnectionString } = require('../config')
配置文件:config.js
// config.js file module.exports = { storageConnectionString: process.env.STORAGE_CONNECTION_STRING || process.env.Storage, keyVaultName: process.env.KEY_VAULT }
我想在测试文件connect-key.spec.js中mock storageConnectionString的值,设想的实现方式如下:
// The connect-key.spec.js file const keyvault_emulator = require('../keyvault-emulator'); const spy = jest.spyOn(keyvault_emulator, 'storageConnectionString'); spy.mockReturnValue('');
请问这种方式是否正确?实现该需求的最优方法是什么?
解答
你的实现方式是否正确?
不正确。因为keyvault-emulator.js是解构导入了config.js里的storageConnectionString,这个值在模块加载时就被存入了keyvault-emulator的局部作用域,并不会成为keyvault_emulator导出对象的属性。你用jest.spyOn去监听不存在的属性,自然会失败。
最优实现方法
方法1:直接mock整个config模块(推荐)
用Jest的jest.mock直接替换config.js模块,指定你需要的mock值,这种方式最直接且不需要改动业务代码:
// connect-key.spec.js // 先mock配置模块,再导入被测试代码 jest.mock('../config', () => ({ storageConnectionString: '你的mock连接字符串', keyVaultName: '任意mock值或保留原值' })); // 导入被测试模块 const { save, retrieve, init } = require('../connect-key'); // 编写测试用例 test('测试save方法', () => { // ...你的测试逻辑 });
模块加载时会直接使用你定义的mock配置,无需考虑加载顺序问题。
方法2:mock环境变量
因为config.js里的storageConnectionString是从环境变量读取的,你可以在测试前直接设置环境变量:
// connect-key.spec.js beforeAll(() => { // 保存原始环境变量,避免影响其他测试 this.originalStorageEnv = process.env.STORAGE_CONNECTION_STRING; process.env.STORAGE_CONNECTION_STRING = '你的mock连接字符串'; }); afterAll(() => { // 测试结束后恢复原始环境变量 process.env.STORAGE_CONNECTION_STRING = this.originalStorageEnv; }); // 必须在设置环境变量之后再导入模块 const { save, retrieve, init } = require('../connect-key'); // 测试用例 test('测试retrieve方法', () => { // ...测试逻辑 });
这种方式适合依赖环境变量的场景,但要严格注意模块导入顺序——必须先设置环境变量再导入被测试模块,否则原始值已经被读取了。
方法3:修改业务代码的导入方式(不推荐)
如果允许改动keyvault-emulator.js,可以把解构导入改成导入整个config对象,这样就能mock其属性:
// 修改后的keyvault-emulator.js const config = require('../config'); // 使用时改为config.storageConnectionString
然后在测试中:
const config = require('../config'); jest.spyOn(config, 'storageConnectionString', 'get').mockReturnValue('你的mock值');
这种方式需要改动业务代码,除非必要否则不推荐。
内容的提问来源于stack exchange,提问作者mcool
相关产品推荐
相关产品推荐

