2013-06-06 4 views
4

배경 : 나는 (유지 보수 목적) 서비스에 싸여 각 $의 자원을 활용 각도 JS 컨트롤러에 대한 단위 테스트를 쓰고 있어요.테스트 AngularJS와 컨트롤러

예 컨트롤러 :

name = 'app.controllers.UsersIndexCtrl' 
angular.module(name, []) 
.controller(name, [ 
    '$scope' 
    '$location' 
    '$dialog' 
    'Users' 
    'UserRoles' 
    ($scope, $location, $dialog, Users, UserRoles) -> 
    # Get users list 
    $scope.users = Users.query() 

    # rest... 

]) 

예 리소스 서비스 : 각도에서

angular.module('app.services.Users', []) 
.factory 'Users', ['$rootScope', '$http', '$resource', '$location' , ($rootScope, $http, $resource, $location)-> 
    baseUrl = '/users' 
    Users = $resource baseUrl + '/:userId', {userId: '@_id'} 

    Users.getStatus = -> 
    console.log 'User::getStatus()' 
    req = $http.get baseUrl + '/status' 
    req.success (res)-> 
     $rootScope.globalUserAccountSettings = res 
     unless $rootScope.$$phase then $rootScope.$apply() 

    # other, custom methods go here... 
]) 

대부분의 단위 테스트 예제는 $ httpBackend를 사용하여 컨트롤러에서 $ HTTP 서비스를 조롱하는 것이 좋습니다. 솔직히 말해서 모든 컨트롤러 테스트에서 요청 경로를 하드 코드해야하므로 유닛 동작을 격리하려는 경우 좋은 연습이 될지 의심 스럽습니다. $ httpBackend mock은 정말 훌륭하지만 컨트롤러에서 $ resource를 직접 사용하는 경우에만 그렇습니다.

httpBackend에게 같을 것이다 $ 사용하여 일반적인 단일 테스트 : 나는 모의 사용자 자원 클래스의 인스턴스를 생성하면 어떻게

it 'should be able to add a new empty user profile', -> 
    $httpBackend.flush() 
    l = $scope.users.length 
    $httpBackend.expect('POST', '/users').respond _.cloneDeep mockResponseOK[0] 
    $scope.add() 
    $httpBackend.flush() 
    expect($scope.users.length).toEqual l + 1 

, 같은 :

angular.module('app.services.Users', []) 
.factory 'Users', -> 
    class Users 
    $save:(cb)-> 
    $remove:-> 
    @query:-> 
    @get:-> 

각도 DI 메커니즘을 무시합니다 오래된 'app.services.Users'모듈을 투명하게 사용하고 jasmine 스파이와 함께 수표를 사용할 수 있도록합니다. 날 귀찮게 무엇

는 내 아이디어를 지원하는 하나의 예를 찾을 수 없습니다 사실이다. 그래서 문제는 어떤 것을 사용하고, 왜 또는 무엇을 잘못하고있는 것입니까?

답변

4

나는 당신이 제안, 재스민 스파이와 서비스 수준이 스텁 훨씬 더 의미가 생각합니다. 서비스가 아닌이 시점에서 컨트롤러를 단위 테스트하고 있습니다. http 요청이 이루어진 정확한 방법은이 테스트에서 중요하지 않습니다.

이처럼 사양에 뭔가를 할 수 있습니다

var Users = jasmine.createSpyObj('UsersStub', ['query', 'get']); 
beforeEach(inject(function($provide) { 
    $provide.factory('Users', function(){ 
    return Users; 
    }); 
}); 

다음 관련 시험에, 당신은 당신의 스파이 객체는 "andCallFake"와 같은 방법을 사용하여 무엇을 기대 반환하는 개별 서비스 메소드 스텁 수 .

var queryResponse = ['mary', 'joseph'], 
    Users = function() { 
    this.query = function() { 
     return queryResponse; 
    }, 
    scope, HomeCtrl; 
}; 

beforeEach(inject(function($rootScope, $controller) { 
    scope = $rootScope.$new(); 
    HomeCtrl = $controller('HomeCtrl', {$scope: scope, Users: new Users()}); 
})); 

it('has users in scope', function() { 
    expect(scope.users).toEqual(queryResponse); 
}); 
+0

beforeEach (모듈 (기능 ($ 제공) {... 대신 분사의 확인 시간이 없었다 ? –

1

가장 좋은 것은 호출 할 가정 된 방법과 가짜 자원을 만들 것입니다. 나는 dsl을 사용하여 coffeescript를 사용하여 테스트를 작성했지만, 오늘날 비슷한 문제가 발생했습니다. 내가 해결 한 방법은 내 리소스에 대한 재 스민 스파이를 만드는 것이 었습니다. 그런 다음 약속을 만들었습니다. 약속이 해결되면 컨트롤러에서 전달하는 '성공'기능을 호출합니다. 그런 다음 '그것'방법으로, 나는 실제로 약속을 해결합니다.

나는 코드를 사용하여이 JS와 재스민과 같을 것이라고 생각하지만 실제로

beforeEach(inject(function($rootScope, $controller, $q) { 
    scope = $rootScope.$new(); 
    queryPromise = $q.defer() 
    User = jasmine.createSpyObject("UsersStub", ["query"]); 
    User.query.andCallFake(function(success,errror){queryPromise.promise.then(success,error)}); 
    HomeCtrl = $controller('HomeCtrl', {$scope: scope, Users: new Users()}); 
})); 

it('has users in scope', function() { 
    queryPrmomise.resolve({User1: {name"joe"}) 
    expect(scope.users).toEqual(queryResponse); 
}); 
0

나는이 물건에 안돼서 : 당신이 할 수있는