Использование Sinon для заглушения прикованных вызовов Mongoose

Я получаю, как заглушить модели Mongoose (благодаря Stubbing модель Mongoose с Sinon), но я не совсем понимаю, как заглушить вызовы вроде:

myModel.findOne({"id": someId})
    .where("someBooleanProperty").equals(true)
    ...
    .exec(someCallback);

Я попробовал следующее:

var findOneStub = sinon.stub(mongoose.Model, "findOne");
sinon.stub(findOneStub, "exec").yields(someFakeParameter);

безрезультатно, какие-либо предложения?

Ответ 1

Я решил это, выполнив следующие действия:

var mockFindOne = {
    where: function () {
        return this;
    },
    equals: function () {
        return this;
    },
    exec: function (callback) {
        callback(null, "some fake expected return value");
    }
};

sinon.stub(mongoose.Model, "findOne").returns(mockFindOne);

Ответ 2

Взгляните на sinon-mongoose. Вы можете ожидать цепных методов всего несколькими строками:

sinon.mock(YourModel).expects('findOne')
  .chain('where').withArgs('someBooleanProperty')
  .chain('exec')
  .yields(someError, someResult);

Вы можете найти рабочие примеры в репо.

Кроме того, рекомендуется использовать метод mock вместо stub, который будет проверять, действительно ли метод существует.

Ответ 3

Если вы используете Promise, вы можете попробовать sinon-as-promised:

sinon.stub(Mongoose.Model, 'findOne').returns({
  exec: sinon.stub().rejects(new Error('pants'))
  //exec: sinon.stub(). resolves(yourExepctedValue)
});

Ответ 4

Другим способом является заглушка или шпионские функции прототипа созданного Запроса (используя синус):

const mongoose = require('mongoose');

sinon.spy(mongoose.Query.prototype, 'where');
sinon.spy(mongoose.Query.prototype, 'equals');
const query_result = [];
sinon.stub(mongoose.Query.prototype, 'exec').yieldsAsync(null, query_result);