2013-04-12 26 views
5

在角度js單元測試中,我想爲每個測試(在「it」方法「)中設置xhr響應,而不是beforeEach方法,但似乎不工作?angular.js如何在每個測試中模擬(或存根)xhr請求

這工作

describe('ExampleListCtrl', function(){ 
    var $scope, $httpBackend; 

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { 
    $httpBackend = _$httpBackend_; 
    $httpBackend.expectGET('examples').respond([]); // <--- THIS ONE 
    $controller(ExampleListCtrl, {$scope: $scope = $rootScope.$new()}); 
    })); 

    it('should create "examples" with 0 example fetched', function() { 
    expect($scope.examples).toBeUndefined(); 
    $httpBackend.flush(); 
    expect($scope.examples).toEqual([]); 
    }); 

}); 

結果

Executed 8 of 8 SUCCESS (0.366 secs/0.043 secs) 

但這種失敗,錯誤當我移動expectGet方法每個方法。我不知道爲什麼。

describe('ExampleListCtrl', function(){ 
    var $scope, $httpBackend; 

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { 
    $httpBackend = _$httpBackend_; 
    $controller(ExampleListCtrl, {$scope: $scope = $rootScope.$new()}); 
    })); 

    it('should create "examples" with 0 example fetched', function() { 
    $httpBackend.expectGET('examples').respond([]); // <--- MOVED TO HERE 
    expect($scope.examples).toBeUndefined(); 
    $httpBackend.flush(); 
    expect($scope.examples).toEqual([]); 
    }); 
}); 

以下是錯誤

.... 
at /Users/me/app/test/unit/controllers/ExampleListCtrlSpec.js:3:1 
     Error: No pending request to flush 
at Error (<anonymous>) 
at Function.$httpBackend.flush (/Users/me/app/test/lib/angular/angular-mocks.js:1171:34) 
at null.<anonymous> (/Users/me/app/test/unit/controllers/ExampleListCtrlSpec.js:14:18) 

---- ----編輯

按照下面的建議,我提出了控制器的beforeEach,改試驗是這樣,這樣我可以不止一次地測試$ httpBackend.expectGET。

describe('ExampleListCtrl', function(){ 
    var $scope, $rootScope, $httpBackend; 

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { 
    $httpBackend = _$httpBackend_; 
    controller = $controller; 
    $scope = $rootScope.$new(); 
    })); 

    it('should create "examples" model with 0 example fetched from xhr', function() { 
    $httpBackend.expectGET('examples').respond([]); 
    controller(ExampleListCtrl, {$scope: $scope}); 
    $httpBackend.flush(); 
    expect($scope.examples).toEqual([]); 
    }); 

}); 

回答

7

這是因爲,一旦你實例化你的控制,它取$http,因此,$httBackend。所以,所有的期望都應該在要求之前做出。

如果您想將$httpBackend.expectGet移動到規範(it區塊),那麼您還需要在預期之後移動$controller(ExempleListCtrl, ...

+1

@ bighostkim在控制器負載上發出這些請求時出現問題,請考慮抽象出$ rootScope並在app.run()上初始化。但由於Caio指出,你的測試失敗了。 – Lucas

+0

如果你遵循@Lucas的方法,那麼你可以在調用這個方法之前,根據你的需要,只將你的期望移動到規範中,然後發出'$ http'請求。 @盧卡斯,我很好奇,你在談論哪些問題? –

+0

我正在討論每次加載控制器(例如,在兩個控制器/頁面之間導航)時都會發出get請求,從而刷新數據。對我而言,我認爲這是糟糕的用戶體驗。通過將請求移至rootScope,請求僅在應用程序啓動時進行一次,因此在控制器之間導航時不會刷新數據。 – Lucas