Reputation: 2167
I have a mongoose model with a static function that finds an employee document by ID and populates referenced manager
and interviewer
fields.
employeeSchema.statics.findAndPopulateById = function(id) {
return this.findById(id)
.populate("manager", "firstname lastname email")
.populate("interviewer", "email")
.then(employee => {
if (!employee) {
throw new errors.NotFoundError();
}
return employee;
});
}
I understand how to test this function when it doesn't contain the populate chain, but the populate part is throwing me for a loop.
Specifically, I am trying to test that the NotFoundError
exception is thrown when no matching record is found, but I am confused how to mock the findById
method so that .populate()
can be called on the return value.
If I were testing this method without the .populate()
chain, I would do something like
let findByIdMock = sandbox.stub(Employee, 'findById');
findByIdMock.resolves(null);
return expect(Employee.findAndPopulateById('123')).to.be.rejectedWith(errors.NotFoundError);
But this approach, of course, doesn't work when populate is involved. I think I should be returning a mocked query or something similar, but I also need to be able to call populate again on that mock or resolve it as a promise.
How do I write a test for this code? Should my function be structured differently?
Upvotes: 2
Views: 2424
Reputation: 2167
Alright this ended up being easier than I anticipated, I just needed to add a call to .exec()
between my final .populate()
and .then()
to make the test below work.
it("should throw not found exception if employee doesn't exist", () => {
const mockQuery = {
exec: sinon.stub().resolves(null)
}
mockQuery.populate = sinon.stub().returns(mockQuery);
let findById = sandbox.stub(Employee, 'findById');
findById.withArgs(mockId).returns(mockQuery);
return expect(Employee.findAndPopulateById(mockId)).to.be.rejectedWith(errors.NotFoundError);
});
Upvotes: 3