单元测试结束承诺链的函数
Unit test a function that ends the promise chain
假设我在一个名为UserController的类中有一个函数,它沿着这些行做一些事情(其中userService.createUser()
返回一个promise):
function createUser(req, res)
{
const userInfo = req.body;
userService.createUser(userInfo)
.then(function(){res.json({message: "User added successfully"})})
.fail(function(error){res.send(error)})
.done();
}
我如何测试当promise解析时,调用res.json()
,而当promise拒绝时,则调用res.send(error)
?
我试过写这样一个测试:
const userService = ...
const userController = new UserController(userService);
const response = {send: sinon.stub()};
...
const anError = new Error();
userService.createUser = sinon.stub().returns(Q.reject(anError));
userController.createUser(request, response);
expect(response.send).to.be.calledWith(anError);
但测试失败,并显示"response.send从不调用"。在调用res.send(error)
之前,我也尝试过记录一些内容,但记录确实发生了。
我的猜测是expect()
是在执行res.send(error)
之前调用的,因为它是异步的。
我对promise和单元测试还很陌生,这是我的体系结构还是我对promises的使用?
我用Q表示承诺,用mocha、chai、sinon表示单元测试。
当您进行异步调用时,expect
语句会在userController.createUser()
行之后立即调用。因此,当评估断言时,它还没有被调用。
要异步测试代码,您需要在it
语句中声明done
,然后手动调用它以获得结果。
在您的测试文件上:
it('should work', function(done) {
...
userController.createUser(request, response);
process.nextTick(function(){
expect(response.send).to.be.calledWith(anError);
done();
});
});
这将使Mocha(我假设您正在使用它)在调用done()
时评估您的excpect
。
或者,您可以在UserController.createUser
函数上设置cb函数,并在.done()
:上调用它
用户控制器
function createUser(req, res, cb) {
const userInfo = req.body;
userService.createUser(userInfo)
.then(function(){res.json({message: "User added successfully"})})
.fail(function(error){res.send(error)})
.done(function(){ if(cb) cb() });
}
然后在你的测试中:
userController.createUser(request, response, function() {
expect(response.send).to.be.calledWith(anError);
done();
});
假设您使用Mocha或Jasmine作为框架,更简单的方法是按照刚开始的方式进行,但只需完全跳过Sinon(因为这里不需要它,除非您测试收到的实际参数):
// observe the `done` callback - calling it signals success
it('should call send on successful service calls', (done) => {
// assuming same code as in question
...
const response = {send: done};
userController.createUser(request, response);
});
// observe the `done` callback - calling it signals success
it('should call send on failing service calls', (done) => {
// assuming same code as in question
...
const response = {send: err => err? done(): done(new Error("No error received"))};
userController.createUser(request, response);
});
披露:我是Sinon维护团队的一员。
- 从函数返回角度承诺
- 如何按照承诺使用mocha/chai/chai测试ES7异步函数
- 两个函数之间的角度承诺
- 当链接javascript承诺时,如何处理then()函数中的条件
- 角承诺的“then”函数的成功回调的词汇范围是什么?
- JQuery 承诺已经包含回调的函数
- 将同步函数包装到承诺中的最佳方法是什么?
- 在同一函数中解析承诺后返回承诺
- JavaScript中的延期/承诺概念是一个新的概念,还是函数式编程的传统部分
- “未捕获(在承诺中)”在获取“then”方法中调用拒绝函数时
- 使用 Promise 在另一个函数中调用带有 Bluebird 承诺库的函数
- 从承诺返回不返回函数会导致警告
- 尝试编写承诺时出错:承诺解析器对象不是函数
- 如何在恢复函数之前等待 JavaScript 承诺解析
- WinJS,从可能是异步的函数返回一个承诺,也可能不是异步的
- javascript承诺在循环中或如何逐个调用函数
- 按照承诺,通过与chai的函数调用验证已解析承诺的内容
- ES6承诺:如何用参数链接函数
- OfflineAudioContext.startRendering()基于承诺的函数在safari中不起作用
- NodeJS 多函数承诺