2015-01-13 21 views
2

我在我的角度應用程序中爲我的登錄控制器編寫測試,並且在「無效憑證登錄失敗」測試期間,API返回401。問題是auth攔截器(它的工作是拾取401),干預並嘗試執行未正確注入的依賴關係。

這裏的攔截器是如何在我的app.js注入:

$httpProvider.interceptors.push('authInterceptor'); 

而這裏的攔截器的膽量(這是一個工廠):

return { 
    response: function(response){ 
     return response || $q.when(response); 
    }, 
    responseError: function(rejection) { 
     if (rejection.status === 401 && $location.path() !== '/login') { 
      // Clear user state. 
      delete $rootScope.loggedUser; 
      storage.clearAll(); 
      document.cookie = "my_session=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; 

      // Redirect. 
      $location.path("/login"); 
     } 
     return $q.reject(rejection); 
    } 
} 

這是我的測試(針對運行登錄控制器,而不是上述攔截器。理想情況下,攔截器應該永遠不應該在此測試案例中執行):

it('should fail with invalid credentials', inject(function($httpBackend, $location, storage) { 
    $httpBackend.expectPOST('/api/login').respond(401); 
    scope.loginCredentials = {email : '[email protected]', password : 'password'}; 
    scope.login(scope.loginCredentials); 
    $httpBackend.flush(); 
})); 

我的存儲庫的模擬注入像所謂

var LoginCtrl, 
    mockStorage, 
    store, 
    scope; 

// Initialize the controller and a mock scope 
beforeEach(inject(function ($controller, $rootScope, storage, User) { 
    scope = $rootScope.$new(); 
    store = []; 

    mockStorage = storage; 
    spyOn(mockStorage,'get').andCallFake(function(key){ 
     return store[key]; 
    }); 
    spyOn(mockStorage,'set').andCallFake(function(key, val){ 
     store[key] = val; 
    }); 

    LoginCtrl = $controller('LoginCtrl', { 
     $scope: scope, 
     $rootScope: $rootScope, 
     storage: mockStorage, 
     User: User 
    }); 
})); 

問題是在測試中嘲笑存儲庫沒有被攔截調用,而是試圖注入真實的,沒有成功,引起內部庫中的錯誤:

TypeError: Cannot read property 'clear' of undefined 
    at Object.publicMethods.clearAll (/path/to/app/ui/app/bower_components/ngStorage/src/angularLocalStorage.js:178:12) 

有什麼建議嗎?謝謝

+0

你是如何注入模擬存儲?你可以放入這段代碼嗎? –

回答

2

請參閱this answer。你需要覆蓋你的嘲笑之一的真正的存儲服務:

module(function ($provide) { 
     $provide.value('storage', mockStorage); 
    }); 
+2

這樣做,非常感謝。我不得不更深入地模擬存儲庫,但是我在每次測試之前添加了這個,並且攔截器正確地使用了模擬版本。 –

+0

它也適用於我,但我不明白爲什麼。如果在這種情況下的存儲是工廠,不應該是$ provide.factory('storage',mockStorage)? – Mari

+0

否,因爲mockStorage是原始工廠的返回值,而不是工廠本身。 '$ provide.factory'會期望一個返回值被用作注入值的函數。你可以看到[這裏](https://github.com/angular/angular.js/blob/071be609275558f177cdb28d8f8891bd1805af1c/src/auto/injector.js#L699)如何使用[valuefn]包裝函數值(https:// github .com/angular/angular.js/blob/e1fd333ca4abfeefa4db12b48b6b74732f655f98/src/Angular.js#L469)。希望這是有道理的。 – noj