GithubHelp home page GithubHelp logo

nubescope / sinon-mongoose Goto Github PK

View Code? Open in Web Editor NEW
87.0 3.0 29.0 2.04 MB

Extend Sinon stubs for Mongoose methods to test chained methods easily

License: MIT License

JavaScript 100.00%
sinon mongoose chain-methods stub mock

sinon-mongoose's Introduction

sinon-mongoose NPM version Build Status devDependency Status Coverage percentage

Extend Sinon stubs for Mongoose methods to test chained methods easily

Installation

$ npm install sinon-mongoose

IMPORTANT! As of version 2.2.0 we are supporting sinon >= 5. If you are using sinon < 5 you could have some problems due to some breaking changes in sinon 5.

Usage

require('sinon')
require('sinon-mongoose')

With Promises

If you are using a version < 2 of sinon-mongoose we recommend you to use sinon-as-promised to have resolves and rejects methods on stubs.

If you want to test this

MongooseModel.find()
  .limit(10)
  .sort('-date')
  .exec()
  .then(function(result) {
    console.log(result)
  })

Just mock and expects as usual and use chain to expects the chained methods. Finally call resolves or rejects (remember to require sinon-as-promised).

sinon
  .mock(MongooseModel)
  .expects('find')
  .chain('limit')
  .withArgs(10)
  .chain('sort')
  .withArgs('-date')
  .chain('exec')
  .resolves('SOME_VALUE')

See complete example

With callbacks (no Promises)

If you want to test this

MongooseModel.find()
  .limit(10)
  .sort('-date')
  .exec(function(err, result) {
    console.log(result)
  })

Just mock and expects as usually and use chain to expects the chained methods. Finally yields as always.

sinon
  .mock(MongooseModel)
  .expects('find')
  .chain('limit')
  .withArgs(10)
  .chain('sort')
  .withArgs('-date')
  .chain('exec')
  .yields(null, 'SOME_VALUE')

See complete example

Contributors

@jniemin
@joebowbeer
@YasharF

License

MIT © Gonzalo Aguirre

sinon-mongoose's People

Contributors

gaguirre avatar jniemin avatar joebowbeerxealth avatar yasharf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sinon-mongoose's Issues

Cannot chain existing mongoose query object

const query = Model.find(conditions, fields, options);
if (someCondition) {
  query.populate('someField)
}
query.exec(callback);

Trying to test populate is called

sinon.mock(Model)
  .expects('find')
  .chain('populate).withArgs('someField')
  .chain('exec')
  .yields(null, {
    foo: 'bar'
  });

I get the following error:

Uncaught TypeError: Cannot read property 'emit' of undefined

If I remove the chain for 'populate' it works just fine.

Debugging further it looks like the yields is not returning the mock object causing a failure further in the test.

Help needed - How can I mock an error being returned from mongoose?

Hi!

I just started using sinon-mongoose and I'm having a good time so far. But I was wondering if it'd be possible to mock an error condition.

For instance, I have this "production" code:

var sendResponse = require('./sendResponse');
var sendError = require('./sendError');
var Place = require('../model/Place');

function showPlaces(req, res) {
  Place.find((err, places) => {
    if (err) {
      return sendError(res, err);
    }

    if (!places.length) {
      return sendResponse(
        res,
        `@${req.body.user_name} there are no places yet! Why don't you try to create the first one by using the \`/add\` command?`
      );
    }

    const names = places.map(p => `�*${p.name}*`).join('\n');

    return sendResponse(res, `@${req.body.user_name} these are the places in our database: \n${names}`);
  });
}

module.exports = showPlaces;

So far, I've been able to mock Place#find behaviour to return nothing or return an array with elements, and I was wondering if I could somehow have my test going through the if (err) branch.

I'm not sure I've been able to convey my idea, please let me know if I can help clarifying this question.

Thanks a lot!

Not compatible with [email protected] createSandbox (chain is not a function)

Hi there,

I'm happy user of sinon-mongoose 2.2.1 and find it very usefull. It worked just fine until sinon 7.2.3, which was not compatible with created sandbox (sinon.createSandbox) but was compatible with default sandbox.

Starting version 7.2.6 sinon-mongoose is not compatible nor with default nor with created sanbox (sandbox.createSandbox).

I know there is #15 and also PR #19.

EDIT: added test for non default sandbox.

describe('using sinon createSandbox', function() {
    var sanbox = sinon.createSandbox();

    beforeEach(function() {
        sanbox.restore();
    });

    afterEach(function() {
        sanbox.verify();
    });

    it('should work mocking Model', function() {
        var BookMock = sanbox.mock(Book);

        BookMock.expects('find')
            .withArgs('SOME_ARGUMENTS')
            .chain('exec')
            .resolves('RESULT');

        Book.find('SOME_ARGUMENTS')
            .exec()
            .then(function(result) {
                assert.equal(result, 'RESULT');
            });
    });
});

It fails with error:

  2) sinon-mongoose
       using sinon sandbox
         should work mocking Model:
     TypeError: BookMock.expects(...).withArgs(...).chain is not a function
      at Context.<anonymous> (test/index.js:159:10)

Not compatible with Sinon 8.x

Changelog for Sinon: https://github.com/sinonjs/sinon/blob/master/CHANGELOG.md

The following is the error that appears when running the built-in tests after bumping Sinon in the dev dependency list to v8.0.2:

:/mnt/c/temp/sinon-mongoose$ npm test

> [email protected] test /mnt/c/temp/sinon-mongoose
> gulp

[13:46:14] Using gulpfile /mnt/c/temp/sinon-mongoose/gulpfile.js
[13:46:14] Starting 'default'...
[13:46:14] Starting 'static'...
[13:46:25] Finished 'static' after 10 s
[13:46:25] Starting 'test'...
[13:46:25] Starting 'pre-test'...
[13:46:25] Finished 'pre-test' after 112 ms
[13:46:25] Starting 'testTask'...
/mnt/c/temp/sinon-mongoose/lib/index.js:98
sinon.sandbox.mock = sandboxMock
                   ^

TypeError: Cannot set property 'mock' of undefined
    at Object.<anonymous> (/mnt/c/temp/sinon-mongoose/lib/index.js:98:20)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/mnt/c/temp/sinon-mongoose/test/index.js:6:1)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at /mnt/c/temp/sinon-mongoose/node_modules/mocha/lib/mocha.js:250:27
    at Array.forEach (<anonymous>)
    at Mocha.loadFiles (/mnt/c/temp/sinon-mongoose/node_modules/mocha/lib/mocha.js:247:14)
    at Mocha.run (/mnt/c/temp/sinon-mongoose/node_modules/mocha/lib/mocha.js:576:10)
    at Object.<anonymous> (/mnt/c/temp/sinon-mongoose/node_modules/mocha/bin/_mocha:637:18)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
    at internal/main/run_main_module.js:17:11
-----------|----------|----------|----------|----------|----------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
-----------|----------|----------|----------|----------|----------------|
 lib/      |    11.54 |        0 |        0 |    11.54 |                |
  index.js |    11.54 |        0 |        0 |    11.54 |... 91,92,95,98 |
-----------|----------|----------|----------|----------|----------------|
All files  |    11.54 |        0 |        0 |    11.54 |                |
-----------|----------|----------|----------|----------|----------------|


=============================== Coverage summary ===============================
Statements   : 11.54% ( 6/52 )
Branches     : 0% ( 0/19 )
Functions    : 0% ( 0/9 )
Lines        : 11.54% ( 6/52 )
================================================================================
[13:46:27] 'testTask' errored after 1.93 s
[13:46:27] Error in plugin "gulp-mocha"
Message:
    There were test failures
[13:46:27] 'test' errored after 2.05 s
[13:46:27] 'default' errored after 12 s
npm ERR! Test failed.  See above for more details.

Remove dependency on gulp-nsp

NSP has been acquired by npm and is being deprecated in favour of its functionality being merged into npm. sinon-mongoose can remove its dependency on gulp-nsp since npm automatically will report vulnerabilities in its latest versions when the command npm install is executed.

Removal of unmaintained dependencies

gulp-coveralls is no longer being maintained
#46 is moving sinon-mongoose's dependency to a maintained fork, but in the long run, it might be worth looking into an alternative that is better maintained or perhaps remove the dependency altogether.

isparta is no longer being maintained
The repo is marked with the badge http://unmaintained.tech
For code quality and to reduce npm audit issues I would recommend either to just remove the dependency or find an alternative

gulp-istanbul / istanbul is no longer being maintained
istanbul's deprecation message: "This module is no longer maintained, try this instead: npm i nyc Visit https://istanbul.js.org/integrations for other alternatives." -- source: npm: istanbul.

.expects(...).chain is not a function

Hey,

I have trouble mocking a mongoose model in typescript. I want to create a Unit test for following class:

export class UserMongodbRepository implements UserRepository {

    constructor(@Inject(USER_MODEL_TOKEN) private readonly userModel: Model<User>) {}

    getAll(): Observable<User[]> {
        return Observable.fromPromise(this.userModel.find().exec());
    }
}

The UserMongodbRepository has a dependency on the user model. I want to mock this dependency:

import * as sinon from 'sinon';
import * as sinonMongoose from 'sinon-mongoose';
import { Model } from "mongoose";
import * as mongoose from 'mongoose';

describe('UserMongodbRepository', () => {

    let userMongodbRepository: UserMongodbRepository;
    let userModel: Model<User>;
    let userMock: any;

    beforeEach(() => {
        userModel = mongoose.model('User', UserSchema);
        userMock = sinon.mock(userModel);
        userMongodbRepository = new UserMongodbRepository(userMock);
    });

    describe('#getAll()', () => {
        it('should get all users', async () => {

            userMock
                .expects('find')
                .chain('exec')
                .resolves([]);

            userMongodbRepository.getAll().subscribe(result => {
                expect(result).toEqual([]);
            });
        });
    });
});

However I am getting following error:

TypeError: userMock.expects(...).chain is not a function

Any ideas what I might be doing wrong here?

Failing tests

Just tried to run test on HEAD. There are 3 failed tests:

  1) sinon-mongoose
       should made Mongoose document methods chainables
         #verify chained:
     TypeError: Cannot read property 'events' of undefined
      at Query.exec (node_modules/.registry.npmjs.org/mongoose/5.4.16/node_modules/mongoose/lib/query.js:4078:17)
      at Context.<anonymous> (test/index.js:124:10)

  2) sinon-mongoose
       using sinon sandbox
         Verify chained - expectation.never():
     TypeError: Cannot read property 'events' of undefined
      at Query.exec (node_modules/.registry.npmjs.org/mongoose/5.4.16/node_modules/mongoose/lib/query.js:4078:17)
      at Context.<anonymous> (test/index.js:205:10)

  3) sinon-mongoose
       using sinon sandbox
         "after each" hook for "Verify chained - expectation.never()":
     ExpectationError: Expected limit([...]) once (never called)
      at Object.fail (node_modules/.registry.npmjs.org/sinon/6.1.0/node_modules/sinon/lib/sinon/mock-expectation.js:281:25)
      at Object.verify (node_modules/.registry.npmjs.org/sinon/6.1.0/node_modules/sinon/lib/sinon/mock.js:108:29)
      at Object.chainedVerify [as verify] (lib/index.js:58:20)
      at Object.chainedVerify [as verify] (lib/index.js:60:30)
      at Object.chainedVerify [as verify] (lib/index.js:60:30)
      at /Users/finch/dev/sinon-mongoose/node_modules/.registry.npmjs.org/sinon/6.1.0/node_modules/sinon/lib/sinon/sandbox.js:32:21
      at Array.filter (<anonymous>)
      at applyOnEach (node_modules/.registry.npmjs.org/sinon/6.1.0/node_modules/sinon/lib/sinon/sandbox.js:31:13)
      at Sandbox.verify (node_modules/.registry.npmjs.org/sinon/6.1.0/node_modules/sinon/lib/sinon/sandbox.js:340:9)
      at Context.<anonymous> (test/index.js:149:13)

TypeError: Attempted to wrap undefined property execPopulate as function

When I try to chain execPopulate I get the following error TypeError: Attempted to wrap undefined property execPopulate as function.

Mock code below

        sinon.mock(Activity)
            .expects('create').withArgs(
                {
                    name: 'Test Activity',
                    type: Activity.type.PHOTOBOOTH,
                    configuration: null,
                    event: '5a9bf4f895c8583993407346'
                })
            .chain('populate').withArgs('event')
            .chain('execPopulate')
            .resolves({
                name: 'Test Activity',
                type: Activity.type.PHOTOBOOTH,
                configuration: undefined,
                id: '5a9bf4f895c8583993407347',
                event: {
                    id: '5a9bf4f895c8583993407346'
                }
            })

ExpectationError: Unexpected call

I'm running into an issue. I'm using supertest to do some full route testing, the issue is when I try and mock out my mongoose model in a before() function I run into this error. I think my mongoose model never actually get swapped out with the mock.

The weird thing is, when I run each test individually it all works fine, but when I try and run in a sequence it bunch start to fail. Any ideas?

var     should = require('should'),
        sinon = require("sinon"),
        request = require('supertest'),
        path = require('path'),
        mongoose = require('mongoose'),
        User = mongoose.model('User'),
        Business = mongoose.model('Business'),
        express = require(path.resolve('./config/lib/express'));

        require('sinon-mongoose');

var mockBusiness = {title:"Joe's"}

describe('Order CRUD tests', function () {

    before(function (done) {

        // Get application
        app = express.init(mongoose);
        agent = request.agent(app);

        sinon.mock(Business)
            .expects('findByIdAndUpdate')
            .chain('lean')
            .chain('exec')
            .yields(null, mockBusiness);

        done();
    });

    it('should be able to do stuff', function (done) {
        //......
        //......
        done();
    });

});

Problems on chaining count with where in array plus limit

How do I chain this?

.count({ x: { $in: ['a','b'] }, u }).limit(1).exec()

I've tried

mock.expects('count')
      .chain('limit')
      .chain('exec')
      .resolves(1);

Result:

    ExpectationError: Unexpected call: count({
      x: { $in: ['a','b'] },
      u: 012345678901234567891234
    })
        Expectation met: count([...]) once

I've also tried different chain orders.
I've also tried with

.count({ u }).where('x').in(['a','b']).limit(1).exec()

chaining also where and in and again different order combinations.
Doesn't work.

Using sinon-mongoose with chai-as-promised - opinion

Hello,

I'm new to JS testing, and I saw your examples use the mocha done approach to async methods.
I used chai-as-promised approach instead, and it worked well.
Could you please review this code and give your opinion about this?
Thanks a lot.

product.model.js

var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

var ProductSchema = new mongoose.Schema({
  name: String
});

module.exports = mongoose.model('Product', ProductSchema);

product.dao.js

module.exports = function(model) {
  return {
    findAll: () => {
      return model.find().exec();
    }
  };
};

product.dao.spec.js

var Product = require('../lib/model/product.model');

describe('ProductDao', () => {

  describe('method findAll', () => {
    var ProductMock;

    beforeEach(() => {
      ProductMock = sinon.mock(Product);
    });

    afterEach(() => {
      ProductMock.verify();
      ProductMock.restore();
    });

    it('should resolve a promise with a non-empty object array', () => {
      var expected = [
        {__id: 1, name: 'Product 1'},
        {__id: 2, name: 'Product 2'}
      ];

      ProductMock
        .expects('find')
        .chain('exec')
        .resolves(expected);

      var ProductDao = require('../lib/dao/product.dao')(Product);

      return ProductDao.findAll().should.become(expected);
    });

    it('should reject a promise with an error', () => {
      ProductMock
        .expects('find')
        .chain('exec')
        .rejects('error');

      var ProductDao = require('../lib/dao/product.dao')(Product);

      return ProductDao.findAll().should.be.rejected;
    });
  });

});

How to verify that some functions are not called

I was wondering what is the best way to test that some of the functions are not called. If I chain some expectation, then it resolves it incorrectly. In this case it exec doesn't resolve to "RESULT" but undefined.

it('#fail', function(done) {
      var bookMock = sinon.mock(new Book({ title: 'Rayuela' }));

      bookMock.expects('update')
        .chain('sort').never()
        .chain('exec').resolves("RESULT");

      bookMock.object.update('SOME_ARGUMENTS').exec().then(function(result) {
        try{
          assert.equal(result, 'RESULT');
          bookMock.verify();
          bookMock.restore();         
          done();
        }catch(err){
          done(err)
        }
      });
    });

Also if I try to verify that was sort was called but it was never called, bockMock.verify() passes nicely.

it('#fail', function(done) {
      var bookMock = sinon.mock(new Book({ title: 'Rayuela' }));

      bookMock.expects('update')
        .chain('sort').withArgs("sort parameters")
        .chain('exec').resolves("RESULT");

      bookMock.object.update('SOME_ARGUMENTS').exec().then(function(result) {
        try{ 
          bookMock.verify();
          bookMock.restore();
          assert.fail(false, true, "should fail to mock.verify()");
          done();
        }catch(err){
          done(err)
        }
      });
    });

Seems that bockMock.verify() only calls verify for first expection which is call to 'update' and rest of the chained mocks are not verified

Doesn't support .stub()

I'm using a few things in my project:

  • sandboxing - which seems to work fine
  • stub - which doesn't appear to be supported
  • this syntax: sandbox.stub(Lenders, 'all') - which also appears to be unsupported

It'd be nice if this module supported the full sinon syntax, as it is otherwise really useful.

aggregate chain fail

use sinon-mongoose to mock aggregate method with chain lookup, show err:

var sinon = require('sinon');
require('sinon-as-promised');
require('sinon-mongoose');

   describe("getNewTask", function () {
        var taskQueueMock;
        it("test", function (done) {
            co(function*() {
                try {
                    taskQueueMock = sinon.mock(model.taskQueue);
                    taskQueueMock.expects('aggregate')
                        .chain('lookup')
                        .resolves({
                            "_id" : "57b5fea8bcd0fd2f0df06320"
                            }
                        );
                    var result = yield model.taskQueue.aggregate();
                    console.log(result);
                    done();
                } catch (err) {
                    console.log(err);
                    done(err);
                }
            })
        });
    });

error:

 TypeError: Attempted to wrap undefined property lookup as function
      at Object.wrapMethod (node_modules/sinon/lib/sinon/util/core.js:106:29)
      at Object.expects (node_modules/sinon/lib/sinon/mock.js:88:27)
      at Object.mock.expects (node_modules/sinon-mongoose/dist/index.js:19:37)
      at Function.chain (node_modules/sinon-mongoose/dist/index.js:12:20)
      at test/taskManager.test.js:54:26
      at next (native)
      at onFulfilled (node_modules/co/index.js:65:19)
      at node_modules/co/index.js:54:5
      at co (node_modules/co/index.js:50:10)
      at Context.<anonymous> (test/taskManager.test.js:50:13)

just mock aggregate without chain work

v2.0 and sandbox.restore

Hi ! First, thanks for your work !

I'm using sinon-mongoose with the sandbox feature.
Mocking a model seems to work but only once, that means sandbox.restore doesn't unwrap everything (or whatever sinon is doing).

I looked at the tests in sinon-mongoose and it doesn't seem to test this use case.

I tested it with npm test here :
link to test

count() and lean() support

Hello,

I have this kind of query:
(note it's with co and generators)

var item = yield Model
    .findOne({ id: id })
    .sort({ createdAt: -1 })
    .lean()

or

... setup params
  var result = yield {
    count: Model.find(findParams).count(),
    items: Model.find(findParams).sort(sort).limit(limit).skip(limit * page).lean()
  }

I am a bit new to testing mongoose this way, but currently I have count is not a function or
...lean is not a function.

Feature Request - Handle MongooseModel.method().cursor() streams

The .cursor() method on mongoose model methods returns a readable stream, not a promise. Given how stream-oriented node js, and how you can easilly .pipe your mongoose queries to your server response like so:

const Model = mongoose.model('model', mySchema);

// ...
Model.find().limit(10).cursor().pipe(res);

It would be nice to have a stub method that returned a readable stream like so

MyMock = sinon.stub(Model)
MyMock.expects('find')
      .chain('limit').withArgs(10)
      .chain('cursor')
      .streams([1,2,3])

For now, the only way I can do this is to create a custom readable stream that the mock returns like so.

const Readable = require('stream').readable,
      rs = new Readable({objectMode: true}),
      array = [1,2,3];
array.forEach(x => rs.push(x));
rs.push(null);

MyMock.expects('find')
      .chain('limit').withArgs(10)
      .chain('cursor')
      .returns(rs);

Mock model constructor

Is it possible to mock the model constructor with sinon-mongoose? This package works fine for mocking named model methods but throws an error if the method name is falsy.

MyModel
    .expects('')
    .resolves({});

Thanks!

How to mock virtuals

Hi,
Is it possible to mock the virtuals methods like this :

userSchema.virtual('firstname').get(function firstname () {
  return this.name.split(' ')[0]
})

I tried this but the coverage says i don't pass threw it :

const userNewMock = sinon.mock(new User(fakeUser))
userNewMock
  .expects('get').withArgs('firstname')
  .resolves(fakeUser.firstname)

Thanks.

TypeError: Attempted to wrap undefined property aggregate as function

I have a use case like this

Question.aggregate([{ $match: { topic: quizId } }, { $sample: { size: count * 2 } }]).then(questionsFromDb => (_.uniqBy(questionsFromDb, '_id').slice(0, count)));

but when I try

QuestionMock.expects('aggregate').withArgs([{ $match: { topic: 1 } }, { $sample: { size: 2 } }]) .yield(null, { data: 'data' });
It is giving error

TypeError: Attempted to wrap undefined property aggregate as function

Any idea what's going on?
Thanks in advance.

Is it possible to test middleware

Examples are stubbing out the entire mongoose model and seem to be preventing middleware from being called. Is it possible to test mongoose middleware while mocking?

SomeSchema.pre('save', function(next) {
  // doing some pre save stuff here that I would like to test
});

How to chain query helpers

I use query helpers

animalSchema.query.byName = function(name) {
    return this.find({ name: new RegExp(name, 'i') });
};

var Animal = mongoose.model('Animal', animalSchema);
Animal.find().byName('fido').exec(function(err, animals) {
    console.log(animals);
});

How can i mock the byName call?

Make sure that methods are being called in the right order

I have a handler written this way:

exports.index = Todos => (req, res) => {
  Todos
    .find(req.params)
    .limit(10)
    .exec()
    .then(x => {
      process.end()
      res.send(x)})
}

And i want to test that the methods are called exactly in that order. I'm writing the test like this:

it('should fail', () => {
      var TodoMock = sinon.mock(Todo)
      TodoMock
        .expects('find').withArgs({id: 'some id'})
        .chain('where').withArgs({as:'random'})
        .chain('exec')
        .resolves('lkjdsajlkdsajlkas')
      handler.index(Todo)({params: {id : 'some id'}}, res)
      TodoMock.verify()
    })

But it passes... if i change the expectation object, instead of {id: 'some id'} to anything else it fails. How can i test the order that is being called and the args?

populate support

Is there a way to support populate calls:

  SomeModel.findOne({foo: bar}).populate('childId').exec(function(err, something) {
    ...
  });

Trying the following:

    sandbox.mock(SomeModel)
      .expects('findOne')
      .withArgs({foo: "bar"})
      .chain('populate', 'childId')
      .yields(null, 'RESULT');

But my test dies when trying to make the call to populate.

Readme.md outdated

The following is still part of the readme.md:

Just mock and expects as usual and use chain to expects the chained methods. Finally call resolves or rejects (remember to require sinon-as-promised).

However (going there):
Sinon 2 added resolves and rejects methods and no longer requires this library.

Is it possible to mock a .save() call?

Hi there,

I'm trying to test a function that invokes a mongoose model save(), as per the code below:

var sendResponse = require('./sendResponse');
var sendError = require('./sendError');
var Place = require('../model/Place');

function createPlace(req, res) {
  var newPlace = new Place();

  newPlace.name = req.body.text;

  newPlace.save(err => {
    if (err) {
      return sendError(res, err, req.body.user_name, newPlace.name);
    }

    return sendResponse(
      res,
      `@${req.body.user_name} your new place *${newPlace.name}* has been added!`,
      201
    );
  });
}

module.exports = createPlace;

I've google around and I understand 'save' is not a method on the model, it's a method on the document, and I was wondering if it'd be possible to use sinon-mongoose to easily test what happens within the save call.

I've also checked into the documentation and tried to reuse the expects + chain + yields approach, but couldn't make it work so far.

Thanks a lot!

Upgrade of mongoose to +5.5.x

Upgrade of mongoose was omitted from #46 even though npm audit calls it out to have an issue. I did make an attempt to do the upgrade in package.json, but it looks like that there is a breaking change and it causes npm test to fail.

Does not work with models with schema?

I can't seem to get this to work with our model that are based on Schemas, i get "Cannot read property 'schema' of undefined"

I'm doing something like this:

const SomeModel = mongoose.model(Trip, schema);

const mockModel = sinon.mock(SomeModel);

mockModel.expects('find')
  .chain('limit', 20)
  .yields(null);

const obj = SomeModel.find().limit().exec(); //simplified, but this fails

This breaks when invoking the code path calls exec. Is this something to do with the mocking?

Create after findOne

Good afternoon, I'm trying the next mistake:
TypeError: pastaMock.expects(...).withArgs(...).expects is not a function

My test:

describe('Cria um pasta: cadastra()', () => {
    it('Cria um pasta', () => {
      const respostaEsperada = {
        numero: 1,
        digito: 2013,
      };

      const dados = {
        numero: 4,
        digito: 2013,
      };

      pastaMock.expects('findOne').withArgs({numero: 1, digito: 1, ambiente: '5914b28a13679803ccaa27cf'}).expects('create').withArgs(dados).chain('then').resolves({ statusCode: 201, data: respostaEsperada });

      return pastasController
          .cadastra({ body: dados })
          .then((response) => {
            expect(response.statusCode).to.be.eql(201);
            expect(response.data).to.be.eql(respostaEsperada);
          });
    });
  });

My controller:

cadastra(req) {
        return this.Pastas.findOne({numero: req.body.numero, digito: req.body.digito, ambiente: req.body.ambiente})
            .then((pasta)=>{
                if (!pasta){
                    return this.Pastas.create(req.body)
                        .then(result => CrudPadraoUsuario.defaultResponse(result, HttpStatus.CREATED))
                        .catch(error => trataErros(error, errosAjustados =>
                            CrudPadraoUsuario.errorResponse(errosAjustados, HttpStatus.UNPROCESSABLE_ENTITY),
                        ));
                }
                return CrudPadraoUsuario.errorResponse({'pasta': 'Pasta já cadastrada'}, HttpStatus.UNPROCESSABLE_ENTITY);
            })
            .catch(error => trataErros(error, errosAjustados =>
                CrudPadraoUsuario.errorResponse(errosAjustados, HttpStatus.UNPROCESSABLE_ENTITY),
            ));
    }

I can not seem to find the problem

Chain fn does not work properly

Use case 1

Implementation :

return Model.find(queryObj)
        .skip(optionObj.skip)
        .limit(optionObj.limit)
        .lean()
        .exec();

Test case :

AgentModelMock.expects('find')
        .chain('skip', 0) //(page - 1) * pageSize
        .chain('limit', Constants.AgentsQueryDefaults.PageSize)
        .chain('lean')
        .chain('exec')
        .resolves(testData.DbMock.agents);

Output: Works fine.

Use case 2

Implementation :

       const query = Model.find(queryObj);
        
        if (optionObj && optionObj.skip) { query.skip(optionObj.skip); }
        if (optionObj && optionObj.limit) { query.limit(optionObj.limit); }
        if (optionObj && optionObj.sort) { query.sort(optionObj.sort); }

        return query.lean().exec();

Test case :

        AgentModelMock.expects('find')
        .chain('skip', 0) //(page - 1) * pageSize
        .chain('limit', Constants.AgentsQueryDefaults.PageSize)
        .chain('lean')
        .chain('exec')
        .resolves(testData.DbMock.agents);

Result -

ExpectationError: Expected skip([...]) once (never called)

Cannot read property '$handleCallbackError' of undefined

Dependencies:

"mongoose": "5.7.3",
"sinon": "7.5.0",
"sinon-mongoose": "2.3.0",

Sample app code

const query = Car.find();
query.limit(10);
const rows = await query.lean();

Test code:

sinon.mock(Car)
      .expects('find')
      .chain('limit')
      .withArgs(10)
      .chain('lean')
      .resolves([]);

Error

      TypeError: Cannot read property '$handleCallbackError' of undefined
          at Query.exec (...\node_modules\mongoose\lib\query.js:4305:25)
          at Query.Object.<anonymous>.Query.then (...\node_modules\mongoose\lib\query.js:4367:15)
          at then (...\server\handlers\cars\list.js:51:37)
          at Object.list (...\server\handlers\cars\list.test.js:40:11)
          at Object.asyncJestTest (...\node_modules\jest-jasmine2\build\jasmineAsyncInstall.js:102:37)
          at ...\node_modules\jest-jasmine2\build\queueRunner.js:43:12
          at new Promise (<anonymous>)
          at mapper (...\node_modules\jest-jasmine2\build\queueRunner.js:26:19)
          at ...\node_modules\jest-jasmine2\build\queueRunner.js:73:41
          at processTicksAndRejections (internal/process/task_queues.js:93:5)

If a remove .chain('limit').withArgs(10) there is no error

sinon.mock(Car)
      .expects('find')
      .chain('lean')
      .resolves([]);

Install failing with unmet sinon peer dependency

I'm trying to setup sinon-mongoose in my project, but npm install -D sinon-mongoose fails with UNMET PEER DEPENDENCY [email protected].

I'm a complete newbie at unit testing with JS, so I might as well be doing something wrong. Here's my current package.json:

{
  "name": "slack-lunch",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon server.js",
    "test": "./node_modules/.bin/mocha --recursive --compilers js:babel-core/register",
    "tdd": "./node_modules/.bin/mocha --recursive --compilers js:babel-core/register -w"
  },
  "keywords": [
    "slack",
    "lunch",
    "express",
    "node"
  ],
  "author": "felipecao",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.17.1",
    "ejs": "^2.5.6",
    "express": "^4.15.2",
    "mongodb": "^2.2.25",
    "mongoose": "^4.9.2",
    "mongoose-random": "^0.1.1"
  },
  "devDependencies": {
    "babel-core": "^6.24.0",
    "babel-loader": "^6.4.1",
    "babel-preset-es2015": "^6.24.0",
    "chai": "^3.5.0",
    "mocha": "^3.2.0",
    "nodemon": "^1.11.0",
    "proxyquire": "^1.7.11",
    "sinon": "^2.1.0",
    "sinon-mongoose": "^1.3.0"
  }
}

And this is the console output of npm install -D sinon-mongoose --verbose:

npm info it worked if it ends with ok
npm verb cli [ '/Users/felipe/.nvm/versions/node/v5.1.0/bin/node',
npm verb cli   '/Users/felipe/.nvm/versions/node/v5.1.0/bin/npm',
npm verb cli   'install',
npm verb cli   '-D',
npm verb cli   'sinon-mongoose',
npm verb cli   '--verbose' ]
npm info using [email protected]
npm info using [email protected]
npm verb get https://registry.npmjs.org/sinon-mongoose not expired, no request
npm verb cache add spec sinon-mongoose@^1.3.0
npm verb addNamed ">=1.3.0 <2.0.0" is a valid semver range for sinon-mongoose
npm verb addNameRange registry:https://registry.npmjs.org/sinon-mongoose not in flight; fetching
npm verb get https://registry.npmjs.org/sinon-mongoose not expired, no request
npm verb addNamed "1.3.0" is a plain semver version for sinon-mongoose
npm verb afterAdd /Users/felipe/.npm/sinon-mongoose/1.3.0/package/package.json not in flight; writing
npm verb afterAdd /Users/felipe/.npm/sinon-mongoose/1.3.0/package/package.json written
npm verb lock using /Users/felipe/.npm/_locks/staging-113bc65bdcf82ac5.lock for /Users/felipe/workspace/github/slack-lunch/node_modules/.staging
npm verb unbuild node_modules/.staging/sinon-mongoose-1eb3c89e3c82681aae026f0e5665eab6
npm verb gentlyRm don't care about contents; nuking /Users/felipe/workspace/github/slack-lunch/node_modules/.staging/sinon-mongoose-1eb3c89e3c82681aae026f0e5665eab6
npm verb tar unpack /Users/felipe/.npm/sinon-mongoose/1.3.0/package.tgz
npm verb tar unpacking to /Users/felipe/workspace/github/slack-lunch/node_modules/.staging/sinon-mongoose-1eb3c89e3c82681aae026f0e5665eab6
npm verb gentlyRm don't care about contents; nuking /Users/felipe/workspace/github/slack-lunch/node_modules/.staging/sinon-mongoose-1eb3c89e3c82681aae026f0e5665eab6
npm info lifecycle [email protected]~preinstall: [email protected]
npm info linkStuff [email protected]
npm verb linkBins [email protected]
npm verb linkMans [email protected]
npm info lifecycle [email protected]~install: [email protected]
npm info lifecycle [email protected]~postinstall: [email protected]
npm verb unlock done using /Users/felipe/.npm/_locks/staging-113bc65bdcf82ac5.lock for /Users/felipe/workspace/github/slack-lunch/node_modules/.staging
npm verb saving [ { name: 'sinon-mongoose',
npm verb saving     spec: '^1.3.0',
npm verb saving     save: 'devDependencies' } ]
[email protected] /Users/felipe/workspace/github/slack-lunch
├── UNMET PEER DEPENDENCY [email protected]
└── [email protected]

npm WARN EPEERINVALID [email protected] requires a peer of sinon@1 but none was installed.
npm WARN EPACKAGEJSON [email protected] No repository field.
npm verb exit [ 0, true ]
npm info ok

Am I doing anything wrong in my setup? Help is highly appreciated! :)

Update sinon peer dependency?

sinon is at version 4.4.3 but the latest version of sinon-mongoose has a peer dependency on sinon ^2.1.0 (which is not satisfied by a sinon 4.4.3)

[email protected] requires a peer of sinon@^2.1.0 but none is installed. You must install peer dependencies yourself.

Can you change the peer dependency to be compatible with the latest version of sinon?

Support for sinon sandboxes

Seems that if creating mock through sandbox, the chainable is not assigned.

var sandbox = sinon.sandbox.create();
var Mock = sandbox.mock(MyMongooseObject);
Mock.expect('findOne').chain('populate');

This example fails with error:
TypeError: Mock.expects(...).chain is not a function

Using sandbox is more convenient as you can easily just create as many mocks you like and then do sandbox.restore which will restore all mocks rather than restoring each mock separately.

Promise callback never invoked

I am trying to write a unit test for my controllers using sinon-mongoose. My test is as follows.

var carrierController = require('../app_server/api_controllers/carrier');
var Carrier = require('../app_server/models/carrier');
var sinon = require('sinon');
var mongoose = require('mongoose');
require('sinon-as-promised');
require('sinon-mongoose');
it("list returns all carriers with sinon-mongoose", () => {
    var CarrierMock = sinon.mock(Carrier)
      .expects('find').withArgs({})
      .chain('exec')
      .resolves('SOMETHING');
    var response = {};
    carrierController.list({}, response);
    CarrierMock.verify();
  });

and my carriercontroller

var Carrier = require('../models/carrier');
var logger = require('../utils/logger');

module.exports = {
  list(req, res) {
    Carrier.find({}).exec()
      .then((carriers) => {
        console.log('carriers', carriers);
      });
  }
};

The problem I'm seeing is that the .then is never invoked inside of the controller

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.