如何使用Jest测试静态工厂方法内部创建的实例的方法调用?
测试工厂方法内实例方法调用的两种常用方案
方案1:spy类原型上的目标方法
所有实例的公有方法都继承自类原型,你可以在调用工厂方法前,提前在原型上挂载spy,后续工厂内创建的实例调用对应方法时会被spy捕获,适合绝大多数简单测试场景。
以Jest测试框架为例,测试代码如下:
import { MyClass } from './your-class-file' import { DomainEvent } from './your-event-file' test('create工厂满足条件时应调用目标方法', () => { // 提前在原型上spy要测试的方法,示例为原代码中的apply,可替换为你要测试的doSomething const targetMethodSpy = jest.spyOn(MyClass.prototype, 'apply').mockImplementation(jest.fn()) // 调用工厂方法 const instance = MyClass.create(true) // 断言方法被正确调用 expect(targetMethodSpy).toHaveBeenCalledTimes(1) expect(targetMethodSpy).toHaveBeenCalledWith(expect.any(DomainEvent)) // 测试完成后恢复原方法,避免影响其他用例 targetMethodSpy.mockRestore() })
方案2:mock类构造函数,返回提前注入spy的自定义实例
如果你不想污染类原型,或者需要自定义实例的其他属性/方法,可以直接mock类的构造逻辑,让工厂方法内new MyClass()时返回你提前创建好的、已经挂载了spy的实例。
示例代码:
import * as MyClassModule from './your-class-file' import { DomainEvent } from './your-event-file' test('create工厂满足条件时应调用目标方法', () => { // 提前创建实例并挂载spy const mockInstance = new MyClassModule.MyClass() const targetMethodSpy = jest.spyOn(mockInstance, 'apply').mockImplementation(jest.fn()) // mock类的构造函数,所有new操作都返回我们提前准备的实例 const classSpy = jest.spyOn(MyClassModule, 'MyClass').mockReturnValue(mockInstance) // 调用工厂方法 const result = MyClassModule.MyClass.create(true) // 断言 expect(targetMethodSpy).toHaveBeenCalledTimes(1) expect(targetMethodSpy).toHaveBeenCalledWith(expect.any(DomainEvent)) // 恢复mock classSpy.mockRestore() targetMethodSpy.mockRestore() })
注意事项
- 若你要测试的是私有方法,不建议直接spy,优先测试方法调用产生的公有可观测副作用即可,确实需要测试的话可以先把方法调整为protected权限。
- 其他测试框架(如Vitest)的逻辑完全一致,替换对应spy/mock的API即可。
内容的提问来源于stack exchange,提问作者Ngọc Nguyễn
相关产品推荐
相关产品推荐

