使用 sinon 和 chai 测试功能时出现问题

Issue when testing function with sinon and chai

我正在尝试开始对我的项目进行测试,有些事情我能够正确测试,但其他事情则不能。这是我要测试的功能。

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);
    }
}

我要测试的是,是否根据 req.body.type 调用 like() 和 dislike() 函数。这是我的测试文件。

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');
    });
});

测试一直失败,因为它说期望 'like' 被调用一次但它没有。我尝试了很多东西并在 Google 上搜索了很多,但我无法让它工作。如果有人有任何想法,我将不胜感激。

谢谢!

执行此操作的正确方法是 return likedislike 当您存根 findById 方法时。

....

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');
  });
});