Unit-test promise-based code in Angularjs

后端 未结 3 806
走了就别回头了
走了就别回头了 2020-11-28 04:19

I\'m having hard times trying to test promise-based code in Angularjs.

I have the following code in my controller:

    $scope.markAsDone = function(t         


        
相关标签:
3条回答
  • 2020-11-28 04:50

    Another approach would be the following, taken straight out of a controller I was 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; } };
    };
    
    0 讨论(0)
  • 2020-11-28 04:50

    And as yet another option you can avoid having to call $digestby using the Q library (https://github.com/kriskowal/q) as a drop-in replacement for $q e.g:

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

    This way promises can be resolved/rejected outside of the $digest cycle.

    0 讨论(0)
  • 2020-11-28 04:58

    You will still need to mock the services and return a promise, but you should use real promises instead, so you don't need to implement its functionality. Use beforeEach to create the already fulfilled promise and mock the service if you need it to ALWAYS be resolved.

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

    If you'd rather prefer to resolve it in each it block with a different value, then you just expose the deferred to a local variable and resolve it in the spec.

    Of course, you would keep your tests as they are, but here is some really simple spec to show you how it would work.

    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');
    });
    
    0 讨论(0)
提交回复
热议问题