在 Jest 测试中,若需为某个特定用例临时修改 __mocks__ 目录下模块的导出值(如可变 token),不应依赖 jest.spyOn 或 unmock,而应通过作用域内变量声明实现安全、简洁的局部覆盖。
在 jest 测试中,若需为某个特定用例临时修改 `__mocks__` 目录下模块的导出值(如可变 token),不应依赖 `jest.spyon` 或 `unmock`,而应通过作用域内变量声明实现安全、简洁的局部覆盖。
Jest 的 __mocks__ 机制本质是模块级静态替换——它会在导入时提供预定义的模拟值,但这些值一旦被 import 绑定,就成为只读引用(尤其当使用 const 导出时)。因此,试图用 jest.spyOn 修改导出变量、或调用 jest.unmock() 切换回真实模块,均无法改变已导入的绑定值,这也是你遇到失败的根本原因。
✅ 正确做法:在测试用例内部重新声明同名变量,利用 JavaScript 作用域优先级覆盖导入值。该方式不侵入模块本身,不影响其他测试,且语义清晰、零副作用。
以下为完整实践示例:
// __mocks__/example.ts export const token = 'exampleString'; // 推荐使用 const(不可变)提升可预测性
// __tests__/foo.spec.ts
import { token } from '../__mocks__/example.ts';
import foo from '../foo.ts';
describe('foo', () => {
it('uses default token', () => {
expect(foo.doSomething(token)).toBe(/* expected */);
});
it('uses null token for edge-case handling', () => {
const token = null; // ✅ 局部变量声明,屏蔽上方 import 的 token
expect(foo.doSomethingElse(token)).toBe(/* expected */);
});
});⚠️ 注意事项:
- 避免 let/var 导出:若 __mocks__/example.ts 中使用 export let token = ...,虽技术上可重赋值,但易引发测试间状态污染(尤其在 --runInBand 以外的并行模式下)。强烈建议统一用 const + 局部覆盖,保障隔离性。
- 路径需准确:确保 import 路径指向 __mocks__ 下的真实文件(如 ../__mocks__/example.ts),而非被自动 mock 的原模块(如 ../../modules/example),否则可能绕过 mock。
- 不适用于函数内直接访问全局 mock 变量的场景:若被测代码未将 token 作为参数传入,而是直接 import { token } from 'example' 并使用,则必须改用 Jest 的手动 mock 重置机制(如 jest.mock(..., () => ({ token: null })))在单个 it 块中动态重定义整个模块。
总结:Jest 测试中覆盖 __mocks__ 变量的核心原则是「以作用域换隔离」——放弃修改共享状态,转而用局部变量精准控制单个用例的输入。这既符合测试的原子性要求,也规避了 Jest 模块缓存与绑定机制带来的陷阱。

















