Sinon calledWith and calledWithMatch fail for objects EDIT: Sinon spy on object constructor

4.1k views Asked by At

I am new to unit testing and am using Mocha, Sinon and Chai to test NodeJs code. The problem is that my expectation for stub.calledWith() always fails when it is an object, even though the test error shows two objects which are syntactically identical.

I am using Sinon to stub a mongoose model's save method, and checking that this stub is called with the correct details.

The function I am testing:

async function createGroup(details) {
        'use strict';
        Logger.info(`create group called`);
        const group   = new UserGroup(this.formatGroup(details));
        const result = await group.save();
        Logger.verbose(`results of save: ${JSON.stringify(result)}`);
        return result;
}

Unit test

describe('object creation', function () {
        'use strict';
        const saveStub   = sinon.stub(UserGroup.prototype, 'save');
        mongoose.Promise = Promise;
        beforeEach(function (done) {
            saveStub.reset();
            return done();
        });
        after(function (done) {
            saveStub.restore();
            return done();
        });
        it('creates an object without error', async function () {
            const correctDetailsIn   = {
                name: 'stark',
                foo: 'bar',
                bar: 'baz',
                users: [{
                    email: '[email protected]',
                    firstName: 'eddard',
                    surname: 'stark'
                }]
            };
            const persistableDetails = {
                name: 'stark',
                users: [{
                    email: '[email protected]',
                    firstName: 'eddard',
                    surname: 'stark'
                }]
            };
            const expectedDetailsOut = {
                _id: 'someidhere',
                name: 'stark',
                users: [{
                    email: '[email protected]',
                    firstName: 'eddard',
                    surname: 'stark'
                }]
            };
            saveStub.resolves(expectedDetailsOut);
            const res = await userGroupService.createGroup(correctDetailsIn);
            expect(res).to.equal(expectedDetailsOut);
            //I tried the four variations below.
            expect(saveStub).to.be.calledWithMatch(persistableDetails);
            //expect(saveStub).to.be.calledWith(persistableDetails);
            //sinon.assert.calledWithMatch(saveStub, persistableDetails)
            //sinon.assert.calledWith(saveStub, persistableDetails)
        })
    })

The four methods I have tried all fail with some variation of:

AssertionError: expected save to have been called with arguments matching {
  name: "stark",
  users: [{ email: "[email protected]", firstName: "eddard", surname: "stark" }]
}
{
  name: "stark",
  users: [{ email: "[email protected]", firstName: "eddard", surname: "stark" }]
}

I feel like I'm missing something simple to get this working.

EDIT:

So it was something simple (and so blindingly obvious that, of course, I missed it) Model.save() is an instance method, so it's called without parameters. It must be something to do with the Sinon assertions that display the expectation twice, as opposed to expectation and reality.

What I really need to do is figure out how to stub/spy on the Model constructor to ensure that it is called with the right parameters. If anyone knows how to do that, I could reallly do with the help.

0

There are 0 answers