我有一个中间件功能,它检查会话令牌以查看用户是否是管理员用户。如果所有检查都通过但是只调用next(),则该函数不返回任何内容。
如何在对作为Sinon间谍的next()回调进行断言之前,如何等待内部异步Promise(adminPromise)解析?测试目前会失败,因为测试中的断言是在AdminMiddleware.prototype.run中解析promise之前做出的。
功能是:
AdminMiddleware.prototype.run = function (req, res, next) {
let token = req.header(sessionTokenHeader);
let adminPromise = new admin().send()
adminPromise.then(function (authResponse) {
let adminBoolean = JSON.parse(authResponse).payload.admin;
if (adminBoolean !== true) {
return new responseTypes().clientError(res, {
'user': 'validation.admin'
}, 403);
};
next();
});
};
测试:
it('should call next once if admin', function (done) {
stub = sinon.stub(admin.prototype, 'send');
stub.resolves(JSON.stringify({success : true, payload : {admin : true}}));
let nextSpy = sinon.spy();
AdminMiddleware.prototype.run({header: function () {}}, {}, nextSpy);
expect(nextSpy.calledOnce).to.be.true;
done();
});
目前我正在将期望包裹在下面,这将导致测试通过,但看起来像是一个黑客。此外,如果它失败,它将导致未处理的承诺拒绝错误和超时,因为done()没有被调用。
it('should call next once if admin', function (done) {
stub = sinon.stub(admin.prototype, 'send');
stub.resolves(JSON.stringify({success : true, payload : {admin : true}}));
let nextSpy = sinon.spy();
AdminMiddleware.prototype.run({header: function () {}}, {}, nextSpy);
stub().then(function () {
expect(nextSpy.calledOnce).to.be.true;
done();
});
});
答案 0 :(得分:3)
一种解决方案是使用存根而不是间谍。虽然它们是两个不同的东西,但是在这种情况下,我没有看到你因使用匿名间谍而失去任何功能。
AdminMiddleware.prototype.run = function (req, res, next) {
const adminPromise = Promise.resolve()
adminPromise.then(function (authResponse) {
next()
})
}
it('should call next once if admin', function (done) {
const nextSpy = sinon.stub()
nextSpy.callsFake(() => {
expect(nextSpy.called).to.be.true
done()
})
AdminMiddleware.prototype.run({header: function () {}}, {}, nextSpy);
});
此外,您可以完全避免将sinon用于此断言,并执行以下操作:
it('should call next once if admin', function (done) {
let called
const nextSpy = function() {
called = true
expect(called).to.be.true
done()
}
AdminMiddleware.prototype.run({header: function () {}}, {}, nextSpy);
});
在这两个示例中,如果未调用nextSpy,您仍会收到超时错误,无法想出任何合理的方法。如果未处理的承诺拒绝是非常重要的,我想你可以做这样的事情:
nextSpy.callsFake(() => {
try {
expect(nextSpy.called).to.be.false
done()
} catch (e) {
console.log(e)
}
})
由于超时,它仍然会通过测试失败,但它不会抛出未处理的承诺拒绝错误。