我想模拟一个名为Dog的构造函数
Dog = jest.fn(()=>{
return{
name:"spike",
bark:function(){
return "bhow " +this.name;
}
}
})
function foo(){
const d = new Dog();
return d.bark();
}
test("testing foo",()=>{
const result = foo();
expect(Dog).toHaveBeenCalledTimes(1);
expect(result).toBe("bhow spike");
expect(Dog.mock.instances.length).toBe(1);
expect(Dog.mock.instances[0].name).toBe("spike");
//this test failed with expected spike received undefined
});
但expect(Dog.mock.instances[0].name).toBe("spike");
失败,收到未定义的预期峰值
最佳版本24.8.0 节点版本10.15.0
答案 0 :(得分:1)
使用new
运算符调用函数时,将创建一个新对象,并将其作为执行上下文(也称为this
)传递给该函数。如果该函数未显式返回任何内容,则将隐式返回此对象。您可以看看detailed explanation。
还要考虑到arrow function can never be used as a constructor。
来自mock functions的Jest文档:
mockFn.mock.instances
一个数组,其中包含使用new从此模拟函数实例化的所有对象实例。
因此,Jest模拟函数每次都会在instances
属性中存储要传递给函数的对象实例的列表(作为this
传递给函数的新创建的对象)。您可以使用new
运算符来调用它。
但是您的构造函数未使用this
对象,因此它保持为空。这就是为什么当您检查Dog.mock.instances[0].name
时得到undefined
的原因。如果稍微更改构造函数以将 name 属性分配给this
对象,则可以看到测试通过:
Dog = jest.fn(function() {
this.name = "spike";
return{
name:"spike",
bark:function(){
return "bhow " +this.name;
}
}
})
很少使用从构造函数中显式返回对象的方法。定义构造函数的最常用方法是将其属性分配给this
对象。因此,解决问题的方法是将构造函数更改为:
Dog = jest.fn(function() {
this.name = "spike";
this.bark = function(){
return "bhow " +this.name;
}
})
如果不想更改构造函数的定义,另一种解决方案是在测试中使用模拟函数的results
attribute:
test("testing foo",()=>{
const result = foo();
expect(Dog).toHaveBeenCalledTimes(1);
expect(result).toBe("bhow spike");
expect(Dog.mock.instances.length).toBe(1);
expect(Dog.mock.results[0].value.name).toBe("spike");
});