尝试访问mockedFunction.mock.instaces属性在Jest中给出了未定义

时间:2019-05-07 05:51:54

标签: jestjs jest-fetch-mock

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

1 个答案:

答案 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");
});