我在尝试在Angularjs中测试基于承诺的代码时遇到了困难。
我的控制器中有以下代码:
$scope.markAsDone = function(taskId) { tasksService.removeAndGetNext(taskId).then(function(nextTask) { goTo(nextTask); }) }; function goTo(nextTask) { $location.path(...); }
我想对以下情况进行单元测试:
markAsDone
tasksService.removeAndGetNext
goTo
在我看来,没有简单的方法可以分别测试这两种情况。
我要做的第一个测试是:
var noopPromise= {then: function() {}} spyOn(tasksService, 'removeAndGetNext').andReturn(noopPromise);
现在,要测试第二种情况,我需要创建另一个永远不变的虚假承诺resolved。这一切都非常乏味,并且有很多样板代码。
resolved
还有其他测试方法吗?还是我的设计有异味?
您仍然需要模拟服务并返回承诺,但是您应该使用真实的承诺,因此您无需实现其功能。使用beforeEach创建已被兑现承诺,并嘲笑服务,如果你需要它总是被解决。
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块中使用不同的值来解析它,则只需将延期公开给局部变量并在规范中对其进行解析。
it
当然,您可以按原样保留测试,但是这里有一些非常简单的规范可以向您展示它如何工作。
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'); });