尝试访问 mockedFunction.mock.instaces 属性 在 Jest 中给出 undefined

Trying to access mockedFunction.mock.instaces property gives undefined in Jest

我想模拟一个名为 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"); 失败,收到未定义的预期峰值

jest 版本 24.8.0 节点版本 10.15.0

当您使用 new 运算符调用函数时,将创建一个新对象并将其作为执行上下文(也称为 this)传递给该函数。如果该函数没有显式 return 任何内容,则此对象将被隐式 returned。你可以看看 detailed explanation.

此外,请考虑 arrow function can never be used as a constructor.

来自 mock functions 的 Jest 文档:

mockFn.mock.instances

An array that contains all the object instances that have been instantiated from this mock function using 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");
});