Заглушка метода класса с помощью 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({})
danday74
источник
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