2014-02-14 3 views
1

컨트롤러 중 하나를 테스트하려고합니다. 내 문제는 생성 된 $LoginController 개체가 항상 빈 개체이며 내 메서드가 모두 범위 개체에 있다는 것입니다.의존성이 많은 AngularJS 컨트롤러를 삽입하는 방법

형식 오류 : 나는 hasError 기능을 테스트 할 때 다음, 나는이 메시지가 '정의되지 않은'객체가 아닌 다음

내 시험이다 ('$ route.current.params을'평가) : 내 인 LoginController에서

describe('login', function() { 
     var $LoginController = null, $scope, $route, $location, $httpBackend; 
     beforeEach(module('common.base64')); 
     beforeEach(module('myapp.user')); 

     beforeEach(inject(function ($injector, $controller, $rootScope, 
            _$location_, _$timeout_, _$route_, _Base64_) 
     { 
      $httpBackend = $injector.get('$httpBackend'); 
      $scope = $rootScope.$new(); 
      $route = _$route_; 
      $location = _$location_; 
      $LoginController = $controller('LoginController', { 
       $scope : $scope, $http: $httpBackend, $location: _$location_, 
       $timeout: _$timeout_, $route: _$route_, Base64: _Base64_} 
      ); 
      console.log($LoginController); // <-- Log: {} 
      console.log($scope);   // <-- Log: { <lots of stuff> } 
     })); 

     describe('LoginController', function() { 
      it('should have been injected', inject(function() { 
        expect($LoginController).toBeTruthy(); 
       } 
      )); 
     }); 

     describe('hasError', function() { 
       it('should return error', inject(function() { 
         $location.url('/login?loginError=true'); 

         expect($scope.hasError).toBeTruthy();   
            // ^-- hasError is defined! 
         expect($LoginController.hasError).toBeTruthy(); 
         //      ^-- hasError is undefined! 
        } 
       )); 
      } 
     ); 
    } 
); 

hasError 기능은 다음과 같이 정의된다 :

$scope.hasError = function() { 
     if($route.current.params) { 
      if ($route.current.params['loginError']) { 
       return "error"; 
      } else { 
       return ""; 
      } 
     } 
     return ""; 
    }; 
,536,

그런 다음 요소 클래스 속성에 삽입합니다. 그렇다면 내 코드의 어떤 부분이 잘못 되었습니까? 아니면 컨트롤러 또는 테스트입니까?

+0

시험에 통과 할 수있다. 컨트롤러에 hasError 메서드가있는 이유는 무엇입니까? hasError는 컨트롤러의 코드가 나타내는 범위의 메서드입니다. Base64, $ route 및 $ timeout과 같이 테스트에 사용하지 않는 모든 서비스를 주입 할 필요는 없습니다. –

+0

'this'에 함수를 할당하고'$ scope.LoginController = this'를 설정하는 것이 더 나은 방법일까요? – lanoxx

+1

일부 사람들이 그렇게합니다. 나는 개인적으로 이점을 보지 못한다. 'this '처리는 JavaScript에서의 악몽이며, view는 단순히 foo() 대신 LoginController.foo()를 사용해야합니다. –

답변

4

테스트 결과입니다.

여기에서 테스트에서 라우팅을 사용하지 않으므로 현재 경로를 가져올 수 없습니다. 당신이

_$route_.current = { 
    params: { 
    loginError: 12345 
    } 
}; 

$location 필요하고 ng-mock 모듈을 사용하는 경우 여러 가지 다른 것들 모두가 모의 객체와 스왑 얻을 ... 당신이 나타나는 경우

당신은 명시 적으로 설정할 수 있습니다.

$location을 변경하면 경로 변경이 트리거되지 않습니다.

더 나은 해결책은 현재 경로 자체에 액세스하는 대신 $routeParams 종속성을 사용하도록 컨트롤러를 변경하는 것입니다. 이렇게하면 테스트 생성 중에 테스트를 통과 할 수 있습니다. 당신의 검사 결과에

if($routeParams && $routeParams.loginError) { 
    return "error"; 
} 

return ""; 

그리고는 단순히 $routeParams

$LoginController = $controller('LoginController', { 
    $scope : $scope, $http: $httpBackend, $location: _$location_, 
    $timeout: _$timeout_, 

    // Mock out $routeParams here: 
    $routeParams: {loginError: 'blah' }, 

    Base64: _Base64_} 
); 
관련 문제