如何使用Jest mock测试类内部实例化的封装依赖且不影响其他测试
解决方案
问题根因
你调用jest.mock('./Mystery')后,整个Mystery类已经被替换为Jest的mock构造函数,所有实例方法默认都是返回undefined的mock函数。你直接修改原型上的getNumber方法为固定返回1000的mock函数后,jest.clearAllMocks()仅会清空mock函数的调用次数、入参记录,不会修改mock返回值配置,也不会恢复原型的原方法,因此第二个测试依然会拿到1000的返回值。
可行实现方案(无需修改业务代码、无需依赖注入)
方案1:spyOn搭配mockRestore(通用推荐)
用jest.spyOn监听原型方法,测试结束后调用mockRestore恢复默认实现,也可以全局配置jest.restoreAllMocks()自动清理:
import { Mystery } from './Mystery'; import { TestedClass } from './TestedClass'; jest.mock('./Mystery'); describe('TestedClass', () => { // 所有测试结束后自动恢复所有spy的原实现 afterEach(() => jest.restoreAllMocks()); it('should return the number 1000', () => { jest.spyOn(Mystery.prototype, 'getNumber').mockReturnValue(1000); const provider = new TestedClass(); const result = provider.someMethod(); expect(result).toEqual(1000); }); it('should return undefined', () => { const provider = new TestedClass(); const result = provider.someMethod(); expect(result).toEqual(undefined); }); });
方案2:单测试自定义Mystery的mock实现
每个测试单独设置Mystery构造函数的返回实例,配置完全隔离不会互相影响:
import { Mystery } from './Mystery'; import { TestedClass } from './TestedClass'; jest.mock('./Mystery'); describe('TestedClass', () => { beforeEach(jest.clearAllMocks); it('should return the number 1000', () => { (Mystery as jest.Mock).mockImplementation(() => ({ getNumber: jest.fn().mockReturnValue(1000) })); const provider = new TestedClass(); const result = provider.someMethod(); expect(result).toEqual(1000); }); it('should return undefined', () => { const provider = new TestedClass(); const result = provider.someMethod(); expect(result).toEqual(undefined); }); });
方案3:mockReturnValueOnce(单测试仅调用一次的场景)
如果每个测试中getNumber仅会被调用一次,直接用单次返回值配置即可,无需额外清理:
Mystery.prototype.getNumber = jest.fn().mockReturnValueOnce(1000);
内容的提问来源于stack exchange,提问作者Ryan Peterson
相关产品推荐
相关产品推荐

