2017-01-17 2 views
0

Ich habe einen Dienst namens myHttp, der eine Zusage zurückgibt, und einen Controller, der myHttp zweimal mit verschiedenen Parametern aufruft.Testen von zwei aufgelösten Versprechungen mit Angular/Jasmine

den Controller zu testen, wie ich versuche, so myHttp mit Jasmin spyOn zu verspotten:

beforeEach(inject(function($controller, _$rootScope_, _$q_, myHttp) { 
    $scope = _$rootScope_.$new(); 
    $q = _$q_; 
    deferred = $q.defer(); 
    deferred2 = $q.defer(); 
    spyOn(myHttp, 'call').and.callFake(fake(1)).and.returnValue(deferred.promise); 
    spyOn(myHttp, 'call').and.callFake(fake(2)).and.returnValue(deferred2.promise); 

wo fake ist eine Funktion, die Parameter abruft in myHttp Anruf verwendet werden.

Problem ist, dass ich nicht zweimal die gleiche verspottete Funktion erklären kann. Ich erhalte den folgenden Fehler von Jasmine:

Wie kann dieser Test behoben werden? dies ist das PLUNK

Javascript:

angular.module("mymodule", []) 

.service('myHttp', function($http,$q){ 
    this.call = function(obj) { 
     var defer = $q.defer(); 
     $http({url:obj.url, data:obj.data}) 
       .then(function (response) { 
        defer.resolve(response); 
       }); 
     return defer.promise; 
    }; 
}) 

.controller('ctl', function($scope,myHttp) { 
     $scope.read = function (id){ 
      var data = {}; 
      data.id = id; 
      myHttp.call({url:'/getStudent', data:data}) 
       .then(function(response) { 
        $scope.id = response.id; 
        $scope.name = response.nm; 
        $scope.classId = response.clsid; 

        var data2 = {}; 
        data2.id = $scope.classId; 
        myHttp.call({url:'/getClass', data:data2}) 
         .then(function(response) { 
          $scope.className = response.nm; 
        }); 
       }); 
    }; 
}); 



describe('Testing a Controller that uses a Promise', function() { 
    var $scope; 
    var $q; 
    var deferred; 
    var $timeout; 

    beforeEach(module('mymodule')); 

    beforeEach(inject(function($controller, _$rootScope_, _$q_, myHttp) { 
    $scope = _$rootScope_.$new(); 
    $q = _$q_; 
    deferred = $q.defer(); 
    deferred2 = $q.defer(); 
    spyOn(myHttp, 'call').and.callFake(fake(1)).and.returnValue(deferred.promise); 
    spyOn(myHttp, 'call').and.callFake(fake(2)).and.returnValue(deferred2.promise); 

    $controller('ctl', { 
     $scope: $scope, 
     myHttp: myHttp 
    }); 

    $scope.read(1) 

    })); 

    function fake (option) { 
    if (option==1) 
     return {url:'/getStudent', data: {id: 1}}; 
    else 
     return {url:'/getClass', data: {id: 10}}; 
    } 

    it('should resolve two promises', function() { 

    var student = { 
     id: 1, 
     nm: "John", 
     clsid: 10 
    }; 

    var clazz = { 
     id: 10, 
     nm: "Math" 
    }; 

    deferred.resolve(student); 
    $scope.$apply(); 

    deferred2.resolve(clazz); 
    $scope.$apply(); 

    expect($scope.id).toBe(student.id); 
    expect($scope.name).toBe(student.nm); 
    expect($scope.classId).toBe(student.clsid); 
    expect($scope.className).toBe(clazz.nm); 
    }); 

}); 

Antwort

1

einfach auf myHttp.call einmal und ändern.

var student = { 
    id: 1, 
    nm: "John", 
    clsid: 10 
}; 

var clazz = { 
    id: 10, 
    nm: "Math" 
}; 

spyOn(myHttp, 'call').and.callFake(function(obj) { 
    if (obj.url == '/getStudent') { 
    return $q.when(student); 
    } else if (obj.url = '/getClass') { 
    return $q.when(clazz); 
    } 
    return $q.reject('Mock not supported'); 
}); 

Siehe plunker für voll funktionsfähiges Beispiel.

Und als Seite, Ihr http Aufruf nur

.service('myHttp', function($http,$q){ 
    this.call = function(obj) { 
     return $http({url:obj.url, data:obj.data}); 
    }; 
}) 

weil $http bereits ein Versprechen zurück reduziert werden.

Sie können auch die eckige $httpBackend verwenden, um Ihre http-Aufrufe zu verspotten, anstatt den Jasmin-Spion zu verwenden. Siehe this plunker, die $httpBackend mit einer geringfügigen Änderung zu myHttp.call verwendet.

0

Die sehr allgemeine Antwort ist, dass Sie nicht haben Ihren Spion auf einem Top-Level-before zu erstellen. Sie können ein beforeEach verwenden, das näher an der individuellen Spezifikation ist, oder sogar den Spion in der it-Anweisung erstellen. Sie können auch etwas in Ihrer Fälschung überprüfen, um zu sehen, welches Versprechen Sie basierend auf dem Parameter, mit dem die Fälschung aufgerufen wird, zurückgeben möchten.

In welchem ​​Zustand möchten Sie eigentlich suchen? Normalerweise sollte etwas passieren, nachdem das Versprechen gelöst wurde, und Sie möchten sich das tatsächlich ansehen. Es ist einfacher, Ihnen ein spezifisches Feedback zu geben, wenn Sie am Ende sagen, was Sie anstreben, anstatt zu sagen, was Sie für die richtige Lösung halten, und uns zu fragen, wie wir dazu kommen sollen.

Bitte sehen Sie Ihren gefälschten Funktionsaufruf in den Anforderungsparametern und zurück auf der Anforderung, ein Objekt auf Basis zu nehmen auszuspionieren auch $q.defer: You're doing it wrong

Verwandte Themen