I am trying to start using testing on my projects, and some things I am able to test properly but others don't. Here is the function I want to test.
exports.rateReview = async (req, res, next) => {
try {
const review = await Review.findById(req.body.id);
if (review) {
if (req.body.type === 'like') await review.like();
if (req.body.type === 'dislike') await review.dislike();
}
res.send('Ok');
} catch (err) {
console.log(err);
}
}
What I am trying to test is, if like() and dislike() functions are being called depending on req.body.type. So here it is my test file.
const sinon = require('sinon');
const chai = require('chai');
const sinonChai = require("sinon-chai");
const mongoose = require('mongoose');
const seriesController = require('../../../../src/series-search/controllers/series.controller');
const Review = require('../../../../src/series-search/models/Review');
const expect = chai.expect;
chai.use(sinonChai);
let spyFindById, spyLike, spyDislike;
beforeEach(() => {
spyLike = sinon.spy(Review.prototype, 'like');
spyDislike = sinon.spy(Review.prototype, 'dislike');
spyFindById = sinon.stub(Review, 'findById').returns({});
});
afterEach(() => {
spyLike.restore();
spyDislike.restore();
spyFindById.restore();
});
describe('Series controller', () => {
describe('search()', () => {
});
describe('addReview()', () => {
it('should call findById() with review id');
});
describe('rateReview()', () => {
it('should call review.like() if type is like', (done) => {
const req = {
body: {
id: '123456',
type: 'like'
}
};
const res = {
send: sinon.stub()
};
const spyLike = sinon.spy(review, 'like');
seriesController.rateReview(req, res, null);
expect(spyLike).to.have.been.calledOnce;
done();
});
it('should call review.dislike() if type is dislike');
});
});
The test keeps failing, as it says that expects 'like' to have been called once but it does not. I try a lot of things and search a lot on Google but I can't make it work. If anyone has any idea I would appreciate.
Thanks!
The correct way to do this is to return like
and dislike
when you stub findById
method.
....
let spyFindById, spyLike, spyDislike;
beforeEach(() => {
spyLike = sinon.spy();
spyDislike = sinon.spy();
// spy `like` and `dislike` here so our `review` variable can be spied.
// use `resolves` since it is promised based function
spyFindById = sinon.stub(Review, 'findById').resolves({
like: spyLike,
dislike: spyDislike
});
});
afterEach(() => {
sinon.restore(); // use sinon.restore() is enough if you use the latest Sinon
});
describe('Series controller', () => {
describe('rateReview()', () => {
// no need to use `done` if we can use `async await`
it('should call review.like() if type is like', async () => {
const req = {
body: {
id: '123456',
type: 'like'
}
};
const res = {
send: sinon.stub()
};
await seriesController.rateReview(req, res, null);
expect(spyLike).to.have.been.calledOnce;
});
it('should call review.dislike() if type is dislike');
});
});