[英]Unit-test promise-based code in Angularjs
我很难在 Angularjs 中测试基于 Promise 的代码。
我的控制器中有以下代码:
$scope.markAsDone = function(taskId) {
tasksService.removeAndGetNext(taskId).then(function(nextTask) {
goTo(nextTask);
})
};
function goTo(nextTask) {
$location.path(...);
}
我想对以下情况进行单元测试:
markAsDone
被调用时,它应该调用tasksService.removeAndGetNext
tasksService.removeAndGetNext
完成后,它应该改变位置(调用goTo
)在我看来,没有简单的方法来分别测试这两种情况。
我为测试第一个所做的工作是:
var noopPromise= {then: function() {}}
spyOn(tasksService, 'removeAndGetNext').andReturn(noopPromise);
现在要测试第二种情况,我需要创建另一个始终会resolved
虚假承诺。 这一切都非常乏味,而且有很多样板代码。
有没有其他方法可以测试这些东西? 还是我的设计有味道?
您仍然需要模拟服务并返回承诺,但您应该使用真正的承诺,因此您不需要实现其功能。 使用beforeEach
创建已经实现的承诺并模拟服务,如果你需要它总是被解决。
var $rootScope;
beforeEach(inject(function(_$rootScope_, $q) {
$rootScope = _$rootScope_;
var deferred = $q.defer();
deferred.resolve('somevalue'); // always resolved, you can do it from your spec
// jasmine 2.0
spyOn(tasksService, 'removeAndGetNext').and.returnValue(deferred.promise);
// jasmine 1.3
//spyOn(tasksService, 'removeAndGetNext').andReturn(deferred.promise);
}));
如果您更愿意在每个it
块中使用不同的值解析它,那么您只需将 deferred 暴露给局部变量并在规范中解析它。
当然,你会保持你的测试原样,但这里有一些非常简单的规范来向你展示它是如何工作的。
it ('should test receive the fulfilled promise', function() {
var result;
tasksService.removeAndGetNext().then(function(returnFromPromise) {
result = returnFromPromise;
});
$rootScope.$apply(); // promises are resolved/dispatched only on next $digest cycle
expect(result).toBe('somevalue');
});
另一种方法如下,直接从我正在测试的控制器中取出:
var create_mock_promise_resolves = function (data) {
return { then: function (resolve) { return resolve(data); };
};
var create_mock_promise_rejects = function (data) {
return { then: function (resolve, reject) { if (typeof reject === 'function') { return resolve(data); } };
};
var create_noop_promise = function (data) {
return { then: function () { return this; } };
};
作为另一种选择,您可以通过使用 Q 库( https://github.com/kriskowal/q )作为$q
替代品来避免调用$digest
,例如:
beforeEach(function () {
module('Module', function ($provide) {
$provide.value('$q', Q);
});
});
通过这种方式,可以在 $digest 循环之外解决/拒绝承诺。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.