unit testing结束承诺链的function
假设我在一个名为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(); }
我怎样才能testing,当承诺解决, res.json()
被调用,当承诺拒绝, res.send(error)
被调用?
我已经尝试写这样的testing:
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);
但testing失败,“response.send永远不会被调用”。 我也试过在调用res.send(error)
之前logging一些东西,并且logging发生了。
我的猜测是expect()
在调用res.send(error)
之前被调用,因为它是asynchronous的。
我在承诺和unit testing方面还是比较新的,这是我的架构还是我对promise的使用?
我使用Q来承诺和摩卡,柴,我的unit testing。
由于你有一个asynchronous调用,在userController.createUser()
行之后调用expect
语句。 所以当断言被评估时,它还没有被调用。
要asynchronoustesting你的代码,你将需要在你的it
语句中声明done
,然后手动调用它来获得结果。
在你的testing文件上:
it('should work', function(done) { ... userController.createUser(request, response); process.nextTick(function(){ expect(response.send).to.be.calledWith(anError); done(); }); });
这将使摩卡(我假设你正在使用它)评估你的excpect
,当done()
被称为。
或者,你可以在你的UserController.createUser
函数上设置一个cb函数,并在.done()
上调用它:
UserController的
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() }); }
然后在你的testing中:
userController.createUser(request, response, function() { expect(response.send).to.be.calledWith(anError); done(); });
假设你使用Mocha或者Jasmine作为框架,更简单的方法是在你刚开始的时候继续,但是完全跳过Sinon(因为在这里不需要,除非你testing收到的实际参数):
// 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维护团队的一员。