Заглушка метода класса с помощью Sinon.js


99

Я пытаюсь заглушить метод с помощью sinon.js, но получаю следующую ошибку:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

Я также перешел к этому вопросу ( заглушка и / или издевательство над классом в sinon.js? ), Скопировал и вставил код, но получаю ту же ошибку.

Вот мой код:

Sensor = (function() {
  // A simple Sensor class

  // Constructor
  function Sensor(pressure) {
    this.pressure = pressure;
  }

  Sensor.prototype.sample_pressure = function() {
    return this.pressure;
  };

  return Sensor;

})();

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure").returns(0);

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure", function() {return 0});

// Never gets this far
console.log(stub_sens.sample_pressure());

Вот jsFiddle ( http://jsfiddle.net/pebreo/wyg5f/5/ ) для указанного выше кода и jsFiddle для упомянутого мной вопроса SO ( http://jsfiddle.net/pebreo/9mK5d/1/ ).

Я обязательно включил sinon во внешние ресурсы в jsFiddle и даже jQuery 1.9. Что я делаю не так?

Ответы:


155

Ваш код пытается заглушить функцию Sensor, но вы определили ее Sensor.prototype.

sinon.stub(Sensor, "sample_pressure", function() {return 0})

по сути то же самое, что и это:

Sensor["sample_pressure"] = function() {return 0};

но он достаточно умен, чтобы видеть, что Sensor["sample_pressure"]этого не существует.

Итак, вы бы хотели сделать что-то вроде этого:

// Stub the prototype's function so that there is a spy on any new instance
// of Sensor that is created. Kind of overkill.
sinon.stub(Sensor.prototype, "sample_pressure").returns(0);

var sensor = new Sensor();
console.log(sensor.sample_pressure());

или

// Stub the function on a single instance of 'Sensor'.
var sensor = new Sensor();
sinon.stub(sensor, "sample_pressure").returns(0);

console.log(sensor.sample_pressure());

или

// Create a whole fake instance of 'Sensor' with none of the class's logic.
var sensor = sinon.createStubInstance(Sensor);
console.log(sensor.sample_pressure());

1
Какая вещь устарела?
— loganfsmyth

sinon.stub (Sensor, "sample_pressure", function () {return 0})
— danday74

Это в моем ответе, потому что исходный вопрос конкретно об этом задан. Учитывая, что мой ответ не предлагает это как правильный подход, я не уверен, что вы просите меня изменить. .returns(0)уже делает то же самое, что и .callFake(() => 0).
— loganfsmyth

1
Не похоже, что returnsэто устарело. sinonjs.org/releases/v3.0.0/stubs . @ danday74, дайте ссылку.
— allenhwkim 07

2
@ danday74 .stubс функцией, поскольку третий аргумент удален: github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 Нет ничего плохого в .returnsили .callsFake, поэтому нет ничего плохого в этом ответе.
— loganfsmyth 08

52

Верхний ответ устарел. Теперь вы должны использовать:

sinon.stub(YourClass.prototype, 'myMethod').callsFake(() => {
    return {}
})

Или для статических методов:

sinon.stub(YourClass, 'myStaticMethod').callsFake(() => {
    return {}
})

Или для простых случаев просто используйте возвраты:

sinon.stub(YourClass.prototype, 'myMethod').returns({})

sinon.stub(YourClass, 'myStaticMethod').returns({})

Или, если вы хотите заглушить метод для экземпляра:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})

4
Было бы здорово, если бы вы могли упомянуть конкретную версию для вашего указанного метода, когда он был добавлен, sinonjsто есть, callsFake()более того, для более старых версий, как это можно исключить?
— айчхан

3
При использовании модулей ES6: я создаю заглушку YourClass.get () в тестовом проекте. Тест вызывает другой модуль, который импортирует YourClass. Будет ли модуль YourClass.get () учитывать заглушку? Если нет, есть ли решение?
— Learner

1
Ваши решения работают на меня. Желаю, если я поставлю вам больше очков: D Спасибо.
— Rubel Hasan

5

Я столкнулся с той же ошибкой, пытаясь имитировать метод класса CoffeeScript с помощью Sinon.

Учитывая такой класс:

class MyClass
  myMethod: ->
    # do stuff ...

Вы можете заменить его метод на шпион следующим образом:

mySpy = sinon.spy(MyClass.prototype, "myMethod")

# ...

assert.ok(mySpy.called)

Просто замените spyна stubили по mockмере необходимости.

Обратите внимание, что вам нужно будет заменить assert.okлюбое утверждение, которое есть в вашей среде тестирования.


2

Спасибо @loganfsmyth за подсказку. Мне удалось заставить заглушку работать с методом класса Ember следующим образом:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)

3
Это комментарий. Начинается с благодарности другому ответу и заканчивается дублированием его кода.
— michelpm

5
Не похоже на дублирование - здесь есть Foo.prototype.constructor, где, как в оригинальном ответе, есть Sensor.prototype. Опять же, Foo.prototype.constructorу меня не работает. :)
— shaunc
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.