【问题标题】:angular.js how to mock(or stub) xhr request in each testangular.js 如何在每个测试中模拟(或存根)xhr 请求
【发布时间】:2013-04-12 22:04:00
【问题描述】:

在 Angular js 单元测试中,我想为每个测试设置 xhr 响应(在“it”方法中),而不是在 beforeEach 方法中,但它似乎不起作用。?

这行得通

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([]);
  });

});

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    发生这种情况是因为一旦你实例化了你的控制器,它就会获取$http,从而获取$httBackend。因此,所有期望都应在要求之前做出。

    如果您希望将您的 $httpBackend.expectGet 移动到规范(it 块),那么您还需要在预期之后移动您的 $controller(ExempleListCtrl, ...

    【讨论】:

    • @bighostkim 在控制器加载时发出这些请求存在问题,请考虑抽象到 $rootScope 并在 app.run() 上初始化。但是由于 Caio 所指出的,您的测试失败了。
    • 如果您遵循@Lucas 方法,那么您可以根据需要仅将您的期望转移到规范中,然后再调用将发出$http 请求的此方法。 @Lucas,我​​很好奇,你在说什么问题?
    • 我说的是每次加载控制器时发出获取请求(例如在两个控制器/页面之间导航),这反过来会刷新数据。对我来说,我认为这是糟糕的用户体验。通过将请求向上移动到 rootScope,请求仅在应用启动时发出一次,因此在控制器之间导航时不会刷新数据。
    • @Lucas,说得好。我同意在控制器初始化时运行 $http 是不好的方法。
    • 我再次改变了关于何时加载数据的想法...观看 egghead.io/video/Kr1qZ8Ik9G8 和其他“解决”相关视频,了解加载控制器数据的最佳做法
    猜你喜欢
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多