0

리소스에 대한 래퍼 인 서비스를 호출하는 컨트롤러가 있습니다. 이와 같이 :리소스를 기반으로하는 서비스에 종속 된 컨트롤러 테스트

서비스 메서드의 반환 값은 컨트롤러 내의 변수에 할당됩니다. 일반적으로 변수는 Resource이고 promise을 포함합니다. 약속이 해결되면 변수에 백엔드에서 반환 된 모든 값이 채워집니다. 나는 백엔드에서받은 모델을 수정하기 위해 약속에서을 추적합니다. 그래서 같이 :

this.model = Service.get(); 
    this.model.$promise.then(function(data) { 
     // do something with data 
    }); 

내 컨트롤러 결과 모델 변수의 값을 테스트해야합니다. 이 작업을 수행하는 유일한 방법은 $ httpBackend을 내 서비스의 실제 구현과 함께 사용하는 것입니다. 그러나 내 컨트롤러를 테스트하기 때문에 어떤 값으로 응답하기 위해서는 에 응답 경로 "api/Service/get"httpBackend.when()에 전달해야하기 때문에 이것은 추한 것입니다.

발췌 내 테스트를 형성 :

// call Controller 
$httpBackend.when('GET', '/api/Service/get').respond(someData); 
$httpBackend.flush(); 
expect(scope.model.property).toBe(null); 

이 보인다 완전히 잘못 느낀다. 리소스를 다루기 위해 별도의 서비스를 사용하는 요지는 컨트롤러가 URL과 http 메서드 이름에 대해 알지 못하는 것입니다. 그래서 내가 무엇을해야하니?

다른 말로하면, 내가 테스트하고 싶은 것은 then이 호출되고 내가 필요한 것을 수행한다는 것입니다.

아마도 then에서 호출되는 별도의 서비스를 만들 수 있습니다. 모델에서해야 할 일을 수행합니다. 예를 들어, 하나의 필드를 null로 설정하고 싶은 경우에는 약간의 잔인 함이 느껴집니다. 간단한 조건에 따라.

+0

당신을 위해이 일을 했 ? – tasseKATT

답변

0

테스트 할 컨트롤러에 $http을 사용하지 않는 한 $httpBackend을 사용할 필요가 없습니다.

작성한대로 컨트롤러는 Service 구현에 대해 알 필요가 없습니다. 컨트롤러에서 알 수있는 것은 에 $promise 속성이있는 개체를 반환하는 get 메서드가 있다는 것입니다.

시험에서 Service의 가짜 구현을 사용하고 싶습니다. 유스 케이스, 스파이, 스텁 등을 통해 여러 가지 방법으로 사용할 수 있습니다. 사용 케이스 및 사용중인 테스트 프레임 워크에 따라 다릅니다. 당신도 resolve 또는 reject 약속은 테스트 할 내용에 따라 할 수 있도록, 당신은 테스트에서 deferred에 액세스 할 수있게하려면

var Service = { 
    get: function() { 

    deferred = $q.defer(); 

    return { 
     $promise: deferred.promise 
    }; 
    } 
}; 

:

한 가지 방법은이 같은 가짜 구현을 만드는 것입니다 .

전체 설정 :

var $rootScope, 
    scope, 
    createController, 
    $q, 
    deferred; 

var Service = { 
    get: function() { 

    deferred = $q.defer(); 

    return { 
     $promise: deferred.promise 
    }; 
    } 
}; 

beforeEach(function() { 

    module('App'); 

    inject(function(_$rootScope_, $controller, _$q_) { 

    $rootScope = _$rootScope_; 

    scope = $rootScope.$new(); 

    createController = function() { 
     $controller('MyController', { 
     $scope: scope, 
     Service: Service 
     }); 
    }; 

    $q = _$q_; 
    }); 
}); 

컨트롤러 구현 :

app.controller('MyController', function($scope, Service) { 

    $scope.property = false; 

    $scope.model = Service.get(); 

    $scope.model.$promise.then(function(data) { 

    if (data) { 
     $scope.property = true; 
    } 
    }); 
}); 

그런 다음 올바르게라고 주장하는 가짜 구현 감시 할 수 있습니다. 재스민과

예 :

spyOn(Service, 'get').and.callThrough(); 

당신은 and.callThrough()이 필요하거나 통화가 중단됩니다 당신의 가짜 구현이 사용되지 않습니다.

은 이제 수동으로 컨트롤러를 만드는 약속을 해결하고, 루프를 소화하고 여러 가지 상태를 테스트 할 수 있습니다 트리거에 의해 완벽하게 제어 할 수 있습니다 :

it('Should work', function() { 

    spyOn(Service, 'get').and.callThrough(); 

    expect(Service.get).not.toHaveBeenCalled(); 

    createController(); 

    expect(Service.get).toHaveBeenCalled(); 

    expect(scope.property).toBeFalsy(); 

    deferred.resolve('some data'); 
    $rootScope.$digest(); 

    expect(scope.property).toBeTruthy(); 
}); 

데모 :http://plnkr.co/edit/th2pLWdVa8AZWOyecWOF?p=preview