Vinod Kolla
Vinod Kolla

Reputation: 324

Mocha spies returns callCount 0

I am using mocha, chai and sinon for unit testing in node env. I need to test a scenario where it makes a call to services to fetch the data and return the data.

My controller looks like this:

{
   get model() { return schema},
   async findUser(data) {
      const data = await this.model.find({ id: data.id });
      return data;
   }
}

In my mocha test I am using the Sinon stub to return the model and find function some like this:

sinon.stub(controller, 'model').get(() => ({
    find: () => ({ username: 'asdf' })
}));

My test is working as expected. Now I want to test see if my find method id called once and the arguments passed to it. To do that, i added following code

const spyFind = sinon.spy(controller.model, 'find');
assert.isTrue(spyFind.calledOnce);

This should return true because the spyFind is called and it returned the expected mock value. But when i debug, the spyFind object says isCalled 'false'. Can someone help me understand what am i doing wrong?

Upvotes: 0

Views: 1438

Answers (1)

Mark
Mark

Reputation: 92460

The way your stub is designed it is going to return a new object every time controller.model is called. As result:

controller.model === controller.model // false

So when you try to spy on the find property of controller.model with:

const spyFind = sinon.spy(controller.model, 'find');

Sinon grabs the object returned by controller.model and stubs find on that object. The the next time you call controller.model, for example in your test, you will get a fresh object from controller.model that is not spied on. So the original spy is never called.

I think better approach is to provide a singe stub that is returned by find(), then you can tell if the stub is called:

const sinon = require('sinon')

let controller = {
    get model() { return schema},
    async findUser(data) {
        const data = await this.model.find({ id: data.id });
    return data;
    }
}

let findStub = sinon.stub()
findStub.returns({ username: 'asdf' })

sinon.stub(controller, 'model').get(() => ({
    find: findStub
}));

console.log(controller.model.find()) // { username: 'asdf' }
console.log(findStub.calledOnce);    // true

Upvotes: 1

Related Questions