4

In der zurückkommt, wie ich Unit-Test zu tun, dass postAttributes Funktion ruft sampleService .updateMethod. Ich habe Probleme, seit die updateMethod Versprechen gibt. HierWie Unit-Test-Funktion in einer Steuerung (Jasmin verwenden), die eine Fabrik Service-Anrufe, die unter <strong><em>SampleController</em></strong> einem Versprechen

angular.module('sampleModule') 
     .controller('SampleController', SampleController); 

    SampleController.$inject =['sampleService']; 

    function SampleController(sampleService){ 

    this.postAttributes = function() {  
     sampleService.updateMethod(number,attributes) 
      .then(function(response){ 
       //do something on successful update 
      },function(response){ 
       //do something on unsuccessful update 
      }); 
     }; 

    } 

ist die Fabrik-Service, was ich habe:

angular.module('sampleModule') 
     .factory('sampleService', sampleService); 

    sampleService.$inject = ['$http']; 

    function sampleService($http) { 
     return { 
      getMethod: function(acctNumber){ 
       return $http({ 
        method: 'GET', 
        url: //api endpoint 
       }); 
      }, 
      updateMethod: function(number, attributes){ 
       return $http({ 
        method: 'PUT', 
        url: //api endpoint, 
        data: //payload 
       }); 
      } 
     }; 
    } 

Ich möchte den Werkskundendienst in den Controller-Spezifikation verspotten, anstatt den eigentlichen Dienst direkt in $ Controller Injektion, da die meisten Einheit Prüfrichtlinien spezifizieren, um eine Einheit unter Isolation zu testen.

Beispiel Controller-Spezifikation:

describe('SampleController Test', function(){ 
     var $controller; 
     var service; 

     beforeEach(angular.mock.module('sampleModule')); 

     beforeEach(angular.mock.inject(function(_$controller_){ 
      $controller = _$controller_; 
     })); 

     it('Testing $scope variable', function(){ 
      var sampleController = $controller('SampleController', { 
       sampleService: service, //mocked factory service 
      }); 

      sampleController.postAttributes(); //calling the function first 
      //here I would like to make an assertion to check if 
      //sampleService.updateMethod has been called with certain parameters       
      //how do I do that?? 
     }); 

    }); 

Antwort

3

um gegoogelt und fand eine Lösung, die die Fabrik Service zu verspotten und folgte Versprechen Schaffung Ansatz wie @TehBeardedOne und machte es es aus dem verspotteten Dienst zurückzukehren.

describe('SampleController', function(){ 

     var mockService, controller, deferred, $rootScope; 

     beforeEach(function(){ 

      angular.mock.module('sampleModule'); 

      angular.mock.module(function($provide){ 
       $provide.factory('sampleService', function($q){ 
        function updateMethod(acct, attr){ 
         deferred = $q.defer(); 
         return deferred.promise; 
        } 
        return{updateMethod: updateMethod}; 
       }); 
      }); 

      angular.mock.inject(function($controller, sampleService, _$rootScope_){ 
       $rootScope = _$rootScope_; 
       mockService = sampleService; 
       spyOn(mockService, 'updateMethod').and.callThrough(); 
       controller =$controller('SampleController', { 
        sampleService: mockService, 
       }) 
      }); 
     }); 

     it('postAttributes function should call updateMethod', function(){ 

      controller.postAttributes(); 
      expect(mockService.updateMethod).toHaveBeenCalled(); 
      expect(mockService.updateMethod).toHaveBeenCalledWith(controller.accountNumber, controller.attributes); 
     }); 

     it('postAttributes success block', function(){ 
      controller.postAttributes(); 
      var res = { 
       data: '2323' 
      } 
      deferred.resolve(res); 
      $rootScope.$digest(); 
      expect(//something in success block).toBe(something); 
     }); 

     it('postAttributes failure block', function(){ 
      controller.postAttributes(); 
      var res = { 
       data: '9898' 
      } 
      deferred.reject(res); 
      $rootScope.$digest(); 
      expect(controller.lame).toBe('dont type shit'); 
     }); 

    }); 

Ich habe verspottet die sampleService mit $ Anbieter Service und machte updateMethod ein Versprechen mit $ q zurückzukehren. Später können Sie das Versprechen auflösen oder ablehnen und die Erfolgs- und Fehlerblöcke in einzelnen it-Blöcken testen.

1

Sie einen Spion verwenden, müssen zu prüfen, ob die Funktion aufgerufen wird. Es gibt mehrere Möglichkeiten, dies zu tun, wie Sie sicher schon bemerkt haben. Sie müssen auch $q und $rootScope injizieren, da Sie den Digest-Zyklus wiederholen müssen, um das Versprechen zurückzugeben.

In der Tat, wenn alles, was Sie tun möchten, überprüfen Sie, dass die Funktion aufgerufen wird ein einfacher Spion wird gut funktionieren. Sie müssen das Versprechen nicht einmal zurückgeben. Davon abgesehen, wenn Sie weiter durch die postAttributes() Funktion gehen und andere Sachen innerhalb dieser Funktion testen wollen, dann müssen Sie das Versprechen, das zu tun, zurückgeben. Hier ist der Ansatz, der gut für mich funktioniert. So etwas sollte funktionieren.

describe('SampleController Test', function(){ 
    var $controller; 
    var service; 
    var $q; 
    var $rootScope; 
    var updateMethodDeferred; 
    var ctrl; 
    var mockHttpObject; 

    beforeEach(angular.mock.module('sampleModule')); 

    beforeEach(angular.mock.inject(function(_sampleService_, _$q_, _$rootScope_, _$controller_){ 
     service = _sampleService_; 
     $q = _$q_; 
     $rootScope = _$rootScope_; 
     $controller = _$controller_; 

     mockHttpObject = { 
      //add mock properties here 
     } 

     updateMethodDeferred = $q.defer(); 
     spyOn(service, 'updateMethod').and.returnValue(updateMethodDeferred.promise); 

     ctrl = $controller('SampleController', { 
      sampleService: service, //mocked factory service 
     }); 
    })); 

    it('Testing $scope variable', function(){ 
     ctrl.postAttributes(); 
     expect(service.updateMethod).toHaveBeenCalled(); 
    }); 

    it('Should do something after promise is returned', function(){ 
     ctrl.postAttributes(); 
     updateMethodDeferred.resolve(mockHttpObject); 
     $rootScope.$digest(); 
     expect(/*something that happened on successful update*/).toBe(/*blah*/)   
    }); 
}); 
+0

Versuchte den oben genannten Ansatz, aber später fand heraus, dass ** sampleService ** an sich viele Abhängigkeiten hat. Also, wenn ich obigen Ansatz folgen muss, muss ich auch alle Abhängigkeiten des sampleService injizieren, was der Fall sein sollte, da wir nur Controller testen, sollten wir alle Abhängigkeiten spotten. Momentan versuche ich den Service mit $ prove.factory zu verspotten. Wie kann ich Versprechen vom verspotteten Dienst mit Erfolgs- und Fehlerblöcken zurückgeben ?! – Pramodh

+0

Ich bin mir nicht sicher, warum Sie die Abhängigkeiten für den Dienst auch injizieren müssen. Ich musste das nie tun und einige meiner Dienstleistungen haben auch mehrere Abhängigkeiten. In jedem Fall können Sie deferred.resolve() verwenden, um Ihren Erfolgsblock und deferred.reject() zu treffen, um Ihren Fehlerblock zu treffen. – tehbeardedone