我在尝试在 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);
现在为了测试第二种情况,我需要创建另一个始终已解决
的虚假 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/46797410/