我很难尝试在 Angularjs 中测试基于 promise 的代码。
我的 Controller 中有以下代码:
$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
的虚假 promise 。这一切都非常乏味,而且有很多样板代码。
还有其他方法可以测试这些东西吗?还是我的设计有味道?
最佳答案
您仍然需要模拟服务并返回一个 promise ,但您应该使用真正的 promise ,这样您就不需要实现它的功能。使用 beforeEach
来创建已经实现的 promise ,并在您需要它始终得到解决时模拟该服务。
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
block 中用不同的值解析它,那么您只需将 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');
});
关于javascript - Angularjs 中基于 promise 的单元测试代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16081586/