2015-04-28 57 views
4

我想測試一個Angular服務,它有兩個依賴關係,一個在$ q上,另一個在'myService'上,它也依賴於$ q。

(function() { 
    'use strict'; 

    angular.module('myModule').factory('myService', [ 
     '$q', 
     'apiService', 
     function($q, apiService) { 

      var data = null; 

      function getData() { 
       var deferred = $q.defer(); 

       if (data === null) { 

        apiService.get('url').then(function(result) { 
         data = result; 
         deferred.resolve(data); 
        }, function() { 
         deferred.reject(); 
        }); 
       } else { 
        deferred.resolve(data); 
       } 

       return deferred.promise; 
      } 

      return { 
       getData: getData 
      }; 
     } 
    ]); 
})(); 

我開始寫一個茉莉花測試,如下所示,但有問題嘲笑$ q。我想注入$ q的真實版本而不是模擬版本到'myService'和'apiService',但我不確定如何完成。

'use strict'; 

describe('My service', function() { 
    var qSpy, apiServiceSpy; 

    beforeEach(module('myModule')); 

    beforeEach(function() { 
     qSpy = jasmine.createSpyObj('qSpy', ['defer']); 

     apiServiceSpy = jasmine.createSpyObj('apiServiceSpy', ['get']); 
     apiServiceSpy.get.and.callFake(function() { 
      var deferred = $q.defer(); 
      deferred.resolve('Remote call result'); 
      return deferred.promise; 
     }); 

     module(function($provide) { 
      $provide.value('$q', qSpy); 
      $provide.value('apiService', apiServiceSpy); 
     }); 
    }); 

    it('should get data.', inject(function(myService) { 
     // Arrange 

     // Act 
     var data = myService.getData(); 

     // Assert 
     expect(data).not.toBeNull(); 
    })); 
}); 

編輯 這是基於下面的反應更新的測試。我想我的問題是我認爲我必須提供$ q。

'use strict'; 

describe('My service', function() { 
    var service, apiServiceSpy; 

    beforeEach(module('myModule')); 

    beforeEach(function() { 
     apiServiceSpy = jasmine.createSpyObj('apiServiceSpy', ['get']); 

     module(function($provide) { 
      $provide.value('apiService', apiServiceSpy); 
     }); 
    }); 

    beforeEach(inject(function($q, myService) { 
     service = myService; 

     apiServiceSpy.get.and.callFake(function() { 
      var deferred = $q.defer(); 
      deferred.resolve('Remote call result'); 
      return deferred.promise; 
     }); 
    })); 

    it('should get data.', function() { 
     // Arrange 

     // Act 
     var data = service.getData(); 

     // Assert 
     expect(data).not.toBeNull(); 
    })); 
}); 
+0

你爲什麼要模擬'$ q'呢?有什麼問題只是使用真正的'$ q' – hansmaad

回答

9

您可以使用真正的$ Q。需要注意的是,您應該致電$scope.$apply()解決承諾。

var service; 
var $scope; 
beforeEach(function() { 

    angular.mock.module('app', function ($provide) { 
     $provide.value('apiService', apiServiceSpy); 
    }); 

    angular.mock.inject(function (_myService_, _$rootScope_) { 
     service = _myService_; 
     $scope = _$rootScope_; 
    }); 
}); 

it('works like a charm', function() { 
    var data; 
    service.getData().then(function(d) { 
     data = d; 
    }); 
    $scope.$apply(); // resolve promise 
    expect(data).toBeAwesomeData(); 
}); 
+0

謝謝!我想我的問題是我認爲我必須提供$ q。 – Jason

+0

另一個重要的注意事項:如果你的承諾包含一個$ http請求,你需要在'$ scope。$ apply()'之前執行'$ httpBackend.flush()',否則承諾將無法正確解析。如果你將兩者結合起來,這在大多數情況下是不必要的(因爲$ http被promisified開始),但是我遇到了需要這種方法的組合實例。 – cm92

0

您應該在真正的$q服務中使用。

var rootScope; 
var deferrred; 
var fakeMyService = { getData: function() { return deferred.promise}}; 

beforEach(inject(function($q, $rootScope) { 
    deferred = $q.defer(); 
    rootScope = $rootScope; 
})) 

it('should do something', function() { 
    . . .   

    deferred.resove(<something>); 
    $rootScope.$digest(); 

    . . . 
    expect(. . .) 

}) 
2

您必須使用$injector服務才能獲得真正的角度服務。

$注入器用於檢索提供程序定義的對象實例, 實例化類型,調用方法和加載模塊。

var $q 
beforeEach(inject(function($injector) { 
    $q = $injector.get('$q'); 
})); 
相關問題