4

I am using Mongoose in Node.js and here is my DAO method.

function findPostsByCategoryId(categoryId, first, second) {
    var sortingOrd = { 'createdAt': -1 };
    return Post.find({ 'categoryId': categoryId }).sort(sortingOrd).skip(first).limit(second);
}

Now, I want to stub the method like this in my test case, using Sinon.

describe('findPostsByCategoryId', function () {
    it('should find post by category id', function () {
        var stub = sinon.stub(Post, 'find');
        stub.callsFake(() => {
            return Promise.resolve(posts);
        });
        postDao.findPostsByCategoryId(1, 2, 3).then(response => {
            assert.length(response, 1);
        })
            .catch((error) => {
                assert.isDefined(error);
            });
    });
});

This is returning me an error saying

TypeError: Post.find(...).sort is not a function.

Can you shed light on how to stub a DAO method that has multiple functions linked to it?

Lin Du
  • 88,126
  • 95
  • 281
  • 483
joler-botol
  • 442
  • 1
  • 7
  • 22

2 Answers2

1

To unit test functions chained like this simply chain stub and spy instances and verify that they were called with the expected values:

it('should find post by category id', function () {
  const limitSpy = sinon.spy();
  const skipStub = sinon.stub().returns({ limit: limitSpy });
  const sortStub = sinon.stub().returns({ skip: skipStub });
  const findStub = sinon.stub(Post, 'find').returns({ sort: sortStub });

  postDao.findPostsByCategoryId(1, 2, 3);

  sinon.assert.calledWithExactly(findStub, { 'categoryId': 1 });  // SUCCESS
  sinon.assert.calledWithExactly(sortStub, { 'createdAt': -1 });  // SUCCESS
  sinon.assert.calledWithExactly(skipStub, 2);  // SUCCESS
  sinon.assert.calledWithExactly(limitSpy, 3);  // SUCCESS
});
Brian Adams
  • 43,011
  • 9
  • 113
  • 111
0

Here is the unit test solution:

dao.js:

const Post = require("./models/post");

function findPostsByCategoryId(categoryId, first, second) {
  var sortingOrd = { createdAt: -1 };
  return Post.find({ categoryId: categoryId })
    .sort(sortingOrd)
    .skip(first)
    .limit(second);
}

module.exports = {
  findPostsByCategoryId,
};

./models/post.js:

// simulate Post model
const Post = {
  find(where) {
    return this;
  },
  sort(...args) {
    return this;
  },
  skip(...args) {
    return this;
  },
  limit(n) {},
};

module.exports = Post;

dao.test.js:

const dao = require("./dao");
const Post = require("./models/post");
const sinon = require("sinon");
const { expect } = require("chai");

describe("Name of the group", () => {
  afterEach(() => {
    sinon.restore();
  });
  it("should pass", () => {
    sinon.stub(Post);
    Post.find.returnsThis();
    Post.sort.returnsThis();
    Post.skip.returnsThis();
    const mResponse = { rowCount: 100 };
    Post.limit.resolves(mResponse);

    return dao.findPostsByCategoryId(1, 2, 3).then((response) => {
      expect(response).to.be.eql(mResponse);
      sinon.assert.calledWithExactly(Post.find, { categoryId: 1 });
      sinon.assert.calledWithExactly(Post.sort, { createdAt: -1 });
      sinon.assert.calledWithExactly(Post.skip, 2);
      sinon.assert.calledWithExactly(Post.limit, 3);
    });
  });
});

Unit test result with coverage report:

  54920719
    ✓ should pass


  1 passing (14ms)

-----------------|----------|----------|----------|----------|-------------------|
File             |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files        |    89.66 |      100 |    55.56 |    89.66 |                   |
 54920719        |      100 |      100 |      100 |      100 |                   |
  dao.js         |      100 |      100 |      100 |      100 |                   |
  dao.test.js    |      100 |      100 |      100 |      100 |                   |
 54920719/models |       40 |      100 |        0 |       40 |                   |
  post.js        |       40 |      100 |        0 |       40 |            4,7,10 |
-----------------|----------|----------|----------|----------|-------------------|

Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/54920719

Lin Du
  • 88,126
  • 95
  • 281
  • 483