Попытка получить доступ к свойству mockedFunction.mock.instaces приводит к неопределенности в Jest - PullRequest
1 голос
/ 07 мая 2019

Я хочу смоделировать функцию конструктора с именем 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"); завершается неудачно с ожидаемым всплеском, полученным undefined

jest версия 24.8.0 версия узла 10.15.0

1 Ответ

1 голос
/ 08 мая 2019

Когда вы вызываете функцию с оператором new, создается новый объект и передается в качестве контекста выполнения (он же this) в функцию. Этот объект затем возвращается неявно, если функция не возвращает ничего явно. Вы можете взглянуть на подробное объяснение .

Также учтите, что функцию стрелки нельзя использовать в качестве конструктора .

Из документации 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 фиктивной функции в вашем тесте:

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