sinon запрещает вызов заглушки, даже если она была вызвана

#node.js #unit-testing #express #sinon

#node.js #модульное тестирование #выразить #sinon

Вопрос:

Я использую sinon для заглушки функции res.status , res.status вызывается в обоих приведенных ниже модульных тестах, один проход и другой завершаются неудачей, я даже отладил и перешел построчно и вижу, что функция вызывается, но sinon завершается неудачей и говорит, что функция не была вызвана.

это контроллер, который я тестирую (ActivityController.js )

 exports.findActivity = (req, res) => {
  ActivityService.findActivity(req.params.id, req.user).then(result => {
    res.status(200).json({result: result})
  }).catch(err => {
    res.status(500).json({msg: err.message})
  })
}
  

и вот модульные тесты, первый тест проходит нормально, а второй тест — нет

     it('should return Activity obj with status 200', async () => {
      expectedResult = activity
      sinon.stub(ActivityService, 'findActivity').resolves(expectedResult)
      await ActivityController.findActivity(req, res)
      sinon.assert.calledWith(ActivityService.findActivity)
      expect(res.status.calledOnce).to.equal(true)
      sinon.assert.calledWith(res.status, 200)
    })
    it('should return status 500 on server error', async () => {
      sinon.stub(ActivityService, 'findActivity').rejects()
      await ActivityController.findActivity(req, res)
      sinon.assert.calledWith(ActivityService.findActivity, req.params.id, req.user)
      expect(res.status.calledOnce).to.equal(true)
      sinon.assert.calledWith(res.status, 500)
    })
  

Я отладил второй модульный тест и вижу, что ActivityController выполняет catch и call res.status(500) , но модульный тест завершается неудачей в res.status.calledOnce

Комментарии:

1. не могли бы вы поделиться частью кода о том, как вы определяете res в тесте?

Ответ №1:

Вы сбрасываете res.status заглушку между каждым тестированием? res.calledOnce может быть неверно, поскольку она может вызываться более одного раза.

Комментарии:

1. Да, после каждого выполняемого мной теста sinon.restore() также я проверял res, и callCount установлен в 0, поэтому sinon даже не распознал его как вызванный

Ответ №2:

Похоже, что expect(res.status.calledOnce).to.equal(true) это было вызвано непосредственно перед ожиданием sinon.assert.calledWith .

установка await перед sinon.assert исправила проблему.

итак, правильный код

   it('should return status 500 on server error', async () => {
      sinon.stub(ActivityService, 'findActivity').rejects()
      await ActivityController.findActivity(req, res)
      await sinon.assert.calledWith(ActivityService.findActivity, req.params.id, req.user)
      expect(res.status.calledOnce).to.equal(true)
      sinon.assert.calledWith(res.status, 500)
    })