2016-03-29 10 views
1

Das Modul DefinitionAngular - Testen http Dienste mit httpBackend wirft unerwartete Ausnahme

var module = angular.module('test', []); 
module.provider('client', function() { 
    this.$get = function($http) { 
     return { 
      foo: function() { 
       return $http.get('foo'); 
      } 
     } 
    } 
}); 

module.factory('service', ['client', function(client) { 
    return { 
     bar: function() { 
      return client.foo(); 
     } 
    } 
}]); 

Grundsätzlich Client ist ein Wrapper für http Anrufe, und der Service ist ein Wrapper um den Client-Basisfunktionen.

Ich bin Unit-Test sowohl der Anbieter und der Service mit Karma + Jasmin. Die Provider Tests wie erwartet laufen, aber ich habe ein Problem mit den Service-Tests:

describe('service test', function(){ 
    var service = null; 
    beforeEach(function(){ 
     module('test') 

     inject(function(_service_, $httpBackend, $injector) { 
      service = _service_; 
      $httpBackend = $injector.get('$httpBackend'); 
     }); 
    }); 

    it('should invoke client.foo via service.bar', function() { 
     $httpBackend.expect("GET", "foo"); 
     service.bar(); 
     expect($httpBackend.flush).not.toThrow(); 
    }); 

}); 

I Expected function not to throw, but it threw Error: No pending request to flush !. bekommen. Wenn der Provider auf die gleiche Weise getestet wird, besteht dieser Test. Warum?

+1

Does [diese] (http://stackoverflow.com/a/19586921/771848) helfen? – alecxe

+2

Etwas sieht in Ihrem 'beforeEach()' fischartig aus ... Das beforeEach-Objekt erhält ein Argument von $ httpBackend, und dann überschreiben Sie dieses Argument mit $ httpBackend = $ injector.get ('$ httpBackend'); Aus dem Code, den Sie angezeigt haben, scheint '$ httpBackend' im Block' it() 'wie" undefiniert "zu sein. –

Antwort

1

Wenn Sie Ihren Dienst testen, müssen Sie den Client überspionieren und diesen Mock anstelle des echten Clients einspielen. Ihr Mock kann sich in derselben Datei befinden, wenn Sie ihn nur zum Testen dieses Dienstes oder in einer separaten Datei verwenden, wenn Sie ihn an anderer Stelle erneut verwenden. Auf diese Weise muss $ httpBackend nicht verwendet werden (weil Sie keinen http-Aufruf ausführen), aber Sie müssen einen Bereich verwenden, um das Versprechen zu lösen.

Der Mock-Client:

angular.module('mocks.clientMock', []) 
    .factory('client', ['$q', function($q) { 
     var mock = { 
      foo: function() { 
       var defOjb = $q.defer(); 
       defOjb.resolve({'your data':'1a'}); 
       return defOjb.promise; 
      } 
     }; 
     return mock; 
    }]); 

Mit dem Mock:

describe('service test', function(){ 
    var service, mock, scope; 
    beforeEach(function(){ 
     module('test', 'mocks.clientMock'); 

     inject(function(_service_, $rootScope) { 
      service = _service_; 
      scope = $rootScope.$new(); 
     }); 
    }); 

    it('should invoke client.foo via service.bar', function() { 
     spyOn(client, 'foo').and.callThrough(); 
     service.bar(); 
     scope.$digest(); 
     expect(client.foo).toHaveBeenCalled(); 
    }); 
}); 
Verwandte Themen