1

我对使用诗乃很陌生。我编写了以下测试,但它失败了,因为它res.status总是以未调用的方式返回。

import chai from 'chai';
import 'chai/register-should';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { db } from '../../models';
import * as loginController from '../../controllers/login';

chai.use(sinonChai);

describe('Login controller', () => {

  describe('post function', () => {
    let findOne, req, status, send, res;

    beforeEach(() => {
      findOne = sinon.stub(db.User, 'findOne');
      findOne.resolves(null);
      req = { body: { email: 'test@test.com', password: 'testpassword' }};
      status = sinon.stub();
      send = sinon.spy();
      res = { send: send, status: status };
      status.returns(res);
      loginController.post(req, res);
    });
    afterEach(() => {
      findOne.restore();
    });
    it('should return a 401 status for an invalid email', (done) => {
      res.status.should.be.calledWith(401);
      findOne.restore();
      done();
    });

  });
});

现在控制器中的方法非常简单。它首先使用sequelizefindOne方法。如果它没有找到匹配的电子邮件,它应该抛出一个 401。这就是它的样子:

export function post(req,res) {
  const email = req.body.email;
  const password = req.body.password;

  db.User.findOne({
    where: {email: email}
  }).then(user => {
    if (user) {
      // Other stuff happens here
    } else {
      res.status(401).send('That email address does not exist in our system.');
    }
  }).catch((error) => {
    res.status(500).send(error.message);
  });
}

当我运行测试时,它确实到达了应该返回状态的 else 语句,但是测试失败了,当我检查日志时,它说res.status从未调用过。

4

1 回答 1

2

这里的问题是规范是同步的并且没有考虑到承诺。

出于可测试性的原因,返回一个承诺是有意义的:

export function post(req,res) {
  ...
  return db.User.findOne(...)
  ...
}

async如果路由处理程序是函数,这可以很自然地完成。

由于 Mocha 支持 Promise,因此规范也可以使用async函数而不是done回调:

it('should return a 401 status for an invalid email', async () => {
  const handlerResult = loginController.post(req, res);
  expect(handlerResult).to.be.a('promise');

  await handlerResult;
  res.status.should.be.calledWith(401);
});
于 2017-11-21T15:52:54.303 回答