Заглушить и/или издеваться над классом в sinon.js?

Я создал оболочку базы данных для своего приложения, как показано ниже. Чтобы проверить это, я, очевидно, хотел бы заменить реальную библиотеку базы данных. Я мог бы создать новый класс, который имитирует метод query и перехватывает все входные данные, но использование sinon.js кажется более подходящим, но как мне его использовать?
Какие функции mock или stub в sinon.js мне следует использовать?

wrapper = (function() {

  function wrapper() {}

  wrapper.db = require("database");

  wrapper.prototype.insertUser = function(doc) {
    return this.db.query("INSERT INTO USERS...");
  };

  return wrapper;

})();

person Industrial    schedule 10.10.2012    source источник


Ответы (2)


Вы можете использовать оба для этого.

Mock имеет ожидаемое упорядоченное поведение, которое, если его не соблюдать правильно, приведет к ошибке.

Заглушка похожа на макет, но без порядка, поэтому вы можете вызывать свои методы так, как хотите. По моему опыту, вам почти никогда не нужен макет.

Оба они заменят ваш метод пустым методом или замыканием, если вы его передадите. Это будет что-то вроде этого:

stub = sinon.stub(wrapper , 'insertUser ', function () { return true; });

Затем вы добавляете ожидаемое поведение, чтобы проверить, произошло ли оно.

Мне нравится использовать Jasmine с Jasmine-Sinon за проверку тестов.

person Cristiano Fontes    schedule 10.10.2012
comment
Ой. Итак, было бы лучше заглушить метод insertUser, а не вызов this.db, который делает insertUser? - person Industrial; 10.10.2012
comment
Зависит от того, что вы тестируете, но если вы хотите проверить, вставляет ли insertUser в БД, это будет интеграционный тест, и никакая заглушка не спасет вас от использования реальной логики с некоторыми в БД памяти для подделки Oracle, например, если вы хотите проверить, вызывается ли метод insertUser, когда это необходимо, то способ заглушки метода insertUser может быть способом сделать это... - person Cristiano Fontes; 10.10.2012
comment
Начиная с версии 3.0 это будет stub = sinon.stub(wrapper , 'insertUser ').callsFake( function () { return true; }); - person timbroder; 22.03.2018
comment
stub(obj, 'meth', fn) удален, см. документацию - person user269867; 30.05.2018

Во-первых, я бы немного изменил определение вашего класса (имя класса в верхнем регистре и исправление назначения базы данных):

var Wrapper = (function() {

  function Wrapper() {
    this.db = require("database");
  }

  Wrapper.prototype.insertUser = function(doc) {
    return this.db.query("INSERT INTO USERS...");
  };

  return Wrapper;

})();

Чтобы заглушить весь класс:

var WrapperStub = sinon.spy(function() {
  return sinon.createStubInstance(Wrapper);
});

sinon.createStubInstance создаст экземпляр Wrapper, где каждый метод является заглушкой. sinon.spy позволит нам следить за созданием экземпляра класса.

Таким образом, вы можете выполнять это следующим образом:

// verify instantiation
var wrapper = new WrapperStub();
expect(WrapperStub).to.have.been.calledWithNew;

// verify method stub
wrapper.insertUser.returns('data');
expect(wrapper.insertUser()).to.equal('data');
expect(wrapper.insertUser).to.have.been.calledOnce;

(в утверждениях используются chai и синон-чай)

Я сказал просто «потренируйтесь», потому что этот фрагмент кода не является реальным модульным тестом. Экземпляры и вызовы методов будут выполняться вашим тестируемым субъектом.

Теперь, если вы хотите имитировать зависимость, введенную с помощью require(), например db = require('database') в вашем примере, вы можете попробовать инструмент тестирования, например Jest (но без использования sinon) или sinonquire, который я создал, вдохновленный Jest, но для использования его с sinon плюс ваш любимый инструмент тестирования (у меня mocha). Внутри sinonquire используется тот же метод, показанный выше, для объединения sinon.spyи sinon.createStubInstance для создания класса-заглушки.

person Ricardo Stuven    schedule 28.10.2015
comment
Обновлены ссылки на Jest: facebook.github.io/jest/docs/mock-functions. .html facebook.github.io/jest/docs/ - person jwadsack; 19.05.2017