2013-03-20 19 views
7

Mam prosty kontroler i pierwszą rzeczą, której potrzebuję, jest przypisanie wartości do zakresu.

function TestCtrl($scope, $http) { 
    $scope.listForms = 'some list'; 
} 

następujący test dla kontrolera działa zgodnie z oczekiwaniami:

describe('Testing a controller', function() { 

    var ctrl, scope, httpMock; 

    beforeEach(inject(function($injector) { 
     scope = $injector.get('$rootScope').$new(); 
     ctrl = $injector.get('$controller'); 
     ctrl(TestCtrl, { $scope: scope }); 
    })); 

    it("assigns to scope", function() { 
     expect(scope.listForms).toMatch("some list"); 
    }); 
}); 

Ale kiedy zmienić funkcję aby otrzymać listę z moim API

function TestCtrl($scope, $http) { 
    $http.get('/api/listForms').success(function(list) { 
    $scope.aListOfForms = 'some list'; 
    }); 
} 

i zmiany testowych do

describe('Testing a controller', function() { 

    var ctrl, scope, httpMock; 

    beforeEach(inject(function($injector) { 
     httpMock = $injector.get('$httpBackend'); 

     scope = $injector.get('$rootScope').$new(); 
     httpMock.when('GET', '/tactical/api/listOrderForms').respond("an order form"); 

     ctrl = $injector.get('$controller'); 
     ctrl(TestCtrl, { 
      $scope: scope, 
      $http: httpMock 
     }); 
    })); 

    it("gets the list from the api and assigns it to scope", function() { 
     httpMock.expectGET('tactical/api/listOrderForms'); 
     expect(scope.orderFormList).toMatch("an order form"); 
     httpMock.flush(); 
    }); 
}); 

I ge t następujące błędy:

TypeError: 'undefined' is not a function 
Expected undefined to match 'an order form'. 
Error: No pending request to flush ! 

Czy ktoś wie, co robię źle? Z góry dziękuję.

Odpowiedz

8

$ http używa $httpBackend do rozmawiania z zasobami zewnętrznymi. Wyśmiałeś $httpBackend, ale kontroler nadal musi z nim rozmawiać przez interfejs $http.

ten powinien zrobić:

describe('Testing a controller', function() { 

    var ctrl, scope, httpMock; 

    beforeEach(inject(function($controller, $rootScope, $httpBackend) { 
     httpMock = $httpBackend; 

     scope = $rootScope.$new(); 
     httpMock.when('GET', '/tactical/api/listOrderForms').respond("an order form"); 

     ctrl = $controller; 
     ctrl(TestCtrl, { 
      $scope: scope 
     }); 
    })); 

    it("gets the list from the api and assigns it to scope", function() { 
     httpMock.expectGET('tactical/api/listOrderForms'); 
     httpMock.flush(); 
     expect(scope.orderFormList).toMatch("an order form"); 
    }); 
}); 
+0

Dzięki To naprawdę pomogło, głuptas mnie. –

+0

Ale nigdzie nie zmodyfikowałeś faktycznej implementacji $ httpBackend. Skąd Angular wie, że nie wywołuje (jakiekolwiek) metody znajdują się na prawdziwym obiekcie $ httpBackend, ale zamiast tego wywołuje funkcję httpMock, gdy wywoływana jest funkcja $ http.get()? Jestem strasznie zdezorientowany (nowy w Angular) – Nikhil

+1

Nikhil, $ http poprosi o $ httpBackend, gdy inicjowany jest $ http. $ httpBackend jest singletonem (istnieje tylko jedno wystąpienie), a httpMock jest odnośnikiem do niego. Rejestrowanie wywołań zwrotnych i robienie rzeczy w tej instancji $ httpBackend, która jest współdzielona między testem i $ http, jest tym, co sprawia, że ​​to działa. –

0

Musisz wywołać httpMock.flush() przed oczekiwaniem(). Wywołanie flush symuluje odpowiedź powracającą z "zaplecza", wywołującą funkcję sukcesu powiązaną z żądaniem http.

+0

nie zdawałem sobie sprawy, że powód flush() musiał iść pierwszy, więc nauczyłem się czegoś, zmęczony to w obie strony i ja wciąż te same błędy. –

3

Nie można ręcznie zastąpić usługi $ http jako usługi httpBackend dla kontrolera.

Zmień

ctrl(TestCtrl, { 
     $scope: scope, 
     $http: httpMock 
    }); 

do

ctrl(TestCtrl, { 
     $scope: scope 
    }); 

To powinno działać.

Powiązane problemy