如何仅为Jest中的单个测试套件使用手动Mock功能?
Jest特定测试套件模拟实现方案
你可以通过将模拟挂载、清除逻辑限定在目标describe块内部,实现仅对指定测试套件生效的模拟,以下是两种常用场景的实现方式:
场景1:模拟单个指定函数
使用jest.spyOn配合目标套件内部的生命周期钩子实现,不会污染其他测试套件:
import * as myModule from '../path_of_module/my_module' describe('Suite 1',function(){ // 仅作用于当前Suite 1的所有测试用例 beforeEach(() => { // 模拟myAwesomeFunction,可自定义返回值/实现逻辑 jest.spyOn(myModule, 'myAwesomeFunction').mockReturnValue('模拟返回内容') }) afterEach(() => { // 执行完当前套件的用例后恢复原函数 jest.restoreAllMocks() }) it('test1', done =>{ myModule.myAwesomeFunction() // 调用模拟版本 done() }) it('test2', done =>{ myModule.myAwesomeFunction() // 调用模拟版本 done() }) }) describe('Suite 2',function(){ it('test3', done =>{ myModule.myAwesomeFunction() // 调用原始未模拟版本 done() }) it('test4', done =>{ myModule.myAwesomeFunction() // 调用原始未模拟版本 done() }) })
场景2:模拟整个目标模块
如果需要模拟模块的全部导出内容,不要使用顶层的jest.mock(会作用于文件内所有测试),改用jest.doMock配合动态导入实现:
describe('Suite 1',function(){ beforeEach(() => { // 仅在当前套件范围内模拟整个模块 jest.doMock('../path_of_module/my_module', () => ({ __esModule: true, myAwesomeFunction: jest.fn(() => '模拟返回内容'), // 其他需要模拟的模块导出项 })) }) afterEach(() => { // 清空模块缓存,避免模拟泄漏 jest.resetModules() }) it('test1', done =>{ // 动态导入拿到模拟后的模块 const { myAwesomeFunction } = require('../path_of_module/my_module') myAwesomeFunction() done() }) it('test2', done =>{ const { myAwesomeFunction } = require('../path_of_module/my_module') myAwesomeFunction() done() }) }) describe('Suite 2',function(){ it('test3', done =>{ // 动态导入拿到原始未模拟模块 const { myAwesomeFunction } = require('../path_of_module/my_module') myAwesomeFunction() done() }) it('test4', done =>{ const { myAwesomeFunction } = require('../path_of_module/my_module') myAwesomeFunction() done() }) })
注意事项
- 使用
jest.doMock时不要在文件顶部静态导入目标模块,必须在测试用例内部动态导入才能拿到模拟后的版本。 - 目标套件的
afterEach钩子必须执行模拟恢复/缓存重置操作,否则模拟逻辑会泄漏到其他测试套件。
内容的提问来源于stack exchange,提问作者Emin Bilgic
相关产品推荐
相关产品推荐

