我刚开始使用 Sinon。我编写了以下测试,但它失败了,因为 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();
});
});
});
现在 Controller 中的方法非常简单。它首先使用 sequelize findOne
方法。如果它没有找到匹配的电子邮件,它应该抛出 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
不是曾经打电话过。
最佳答案
这里的问题是规范是同步的,没有考虑到 promise 。
出于可测试性原因返回 promise 是有意义的:
export function post(req,res) {
...
return db.User.findOne(...)
...
}
如果路由处理程序是 async
函数,这可以很自然地完成。
由于 Mocha 支持 promises,规范也可以使用 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);
});
关于javascript - 如何使用 Mocha、Chai 和 Sinon 正确测试 Express Controller 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47415861/