1

我想模拟一个名为 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

4

1 回答 1

3

当您使用运算符调用函数时new,会创建一个新对象并将其作为执行上下文 (aka this) 传递给函数。如果函数没有显式返回任何内容,则该对象将被隐式返回。你可以看看详细的解释

另外,请考虑箭头函数永远不能用作构造函数

来自模拟函数的 Jest 文档:

mockFn.mock.instances

一个数组,其中包含已使用 new 从此模拟函数实例化的所有对象实例。

因此,每次使用运算符调用时,Jest 模拟函数都会在instances属性中存储传递给函数的对象实例列表(作为函数传递的新创建的对象) 。thisnew

但是您的构造函数没有使用该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 属性:

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");
});
于 2019-05-08T07:10:51.230 回答