在Angularjs中基于unit testing承诺的代码

我正在尝试在Angularjs中testing基于承诺的代码。

我在我的控制器中有以下代码:

$scope.markAsDone = function(taskId) { tasksService.removeAndGetNext(taskId).then(function(nextTask) { goTo(nextTask); }) }; function goTo(nextTask) { $location.path(...); } 

我想unit testing下列情况:

  • markAsDone被调用时,它应该调用tasksService.removeAndGetNext
  • tasksService.removeAndGetNext完成时,它应该改变位置(调用goTo

在我看来,没有简单的方法来分别testing这两种情况。

我所做的testing第一个是:

 var noopPromise= {then: function() {}} spyOn(tasksService, 'removeAndGetNext').andReturn(noopPromise); 

现在来testing第二种情况,我需要创build另一个假的承诺,将永远resolved 。 这是非常乏味的,这是很多的样板代码。

有没有其他方法来testing这样的事情? 或者我的devise味道?

您仍然需要模拟服务并返回一个承诺,但是您应该使用真正的承诺,所以您不需要实现其function。 使用beforeEach创build已经履行的承诺,并嘲笑服务,如果你需要它始终得到解决。

 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); })); 

如果你宁愿在每一个块中使用不同的值来解决这个问题,那么你只要将延期的内容暴露给一个局部variables,并在规范中解决它。

当然,你会保持你的testing,但是这里有一些非常简单的规范来告诉你它是如何工作的。

 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'); }); 

另一种方法是直接从我正在testing的控制器中取出:

 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的插入replace来调用$digest ,例如:

 beforeEach(function () { module('Module', function ($provide) { $provide.value('$q', Q); }); }); 

这种承诺可以在$ digest循环之外解决/拒绝。