Jest测试中如何Mock类的静态name属性?
问题场景
目标函数会根据传入类的name静态属性分支执行,代码如下:
function myfunc(injected_class){ if (injected_class.name == "ThingOne"){ // do this } else if (injected_class.name == "ThingTwo"){ // do that } let instance = new injected_class(options) instance.some_instance_method() }
尝试传入Mock类测试时,无法覆盖injected_class.name属性(始终返回mockConstructor),测试代码如下:
let mock_some_instance_method = jest.fn() let mock_injected_class = jest.fn().mockImplementation(() => { return { some_instance_method: mock_some_instance_method } }) mock_some_instance_method.name = "ThingOne" // 此处错误,未给Mock类设置name some_module.myfunc(mock_injected_class)
解决方法
Jest生成的mock函数,其name属性是只读的,直接赋值无法生效,需通过Object.defineProperty强制修改:
let mock_some_instance_method = jest.fn() let mock_injected_class = jest.fn().mockImplementation(() => { return { some_instance_method: mock_some_instance_method } }) // 覆盖mock函数的name属性 Object.defineProperty(mock_injected_class, 'name', { value: 'ThingOne', configurable: true // 可选,允许后续修改该属性 }) some_module.myfunc(mock_injected_class)
也可以直接定义普通函数作为Mock类,再转为Jest mock,这样能直接设置name:
let mock_some_instance_method = jest.fn() // 定义普通函数作为Mock类 function mock_injected_class() { return { some_instance_method: mock_some_instance_method } } // 直接设置name属性 mock_injected_class.name = "ThingOne" // 转为Jest mock函数,保留断言能力 jest.mocked(mock_injected_class) some_module.myfunc(mock_injected_class)
关键说明
- ES6规范中函数的
name属性默认只读,仅能通过Object.defineProperty修改。 - 两种方案都能保留Mock类的实例方法逻辑,同时让
myfunc正确识别name属性分支。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

