如何使用$ httpBackend每次测试只测试一个HTTP请求?

时间:2014-02-24 18:21:34

标签: angularjs unit-testing

假设我有一个控制器,在初始化时使用$ http服务发出3个不同的请求。我想写三个不同的测试,每个测试只关心其中一个请求。

例如,假设控制器看起来像:

app.controller('ExampleCtrl', function($scope, $http) {
  $http.get('/foo', /* ... */);
  $http.get('/bar', /* ... */);
  $http.get('/baz', /* ... */);
});

然后我想写下测试:

describe('ExampleCtrl', function() {
  var http;

  beforeEach(inject(function($httpBackend, $controller) {
    http = $httpBackend;
    $controller('ExampleCtrl');
  }));

  it('loads "/foo" and does whatever', function() {
    http.expectGET('/foo').repond(/* ... */);
    http.flush();
    expect(/* ... */);
  });

  it('loads "/bar" and does whatever else', function() {
    /* etc. */
  });
});

这似乎不起作用,因为从我所看到的,当我调用flush()时Angular假设我必须已经指定所有应该发出的请求。例如,如果我只指定expectGET('/foo'),那么Angular会抱怨'/bar''/baz'有意外请求。

有没有办法做我想在这里做的事情?我是从错误的角度处理这个问题吗?

我意识到,一种方法是,我可以将所有expectGET放在beforeEach中,并仅在测试用例中测试结果。但这似乎是一个不幸的解决方法,不得不在多个地方分散我的期望。

1 个答案:

答案 0 :(得分:2)

我认为http.expectGET('/foo').repond(/* ... */);可以被视为设置代码。毕竟,通过告诉它如何响应来配置模拟。所以我把它放在beforeEach中,不会把它看成是一个工作区。

另一种选择是使用$http使用您自己的间谍/模拟来模拟$provide

beforeEach(module('plunker', function ($provide) {

  $provide.value('$http', {
    get : function(a){
      this.calls = this.calls || [];
      this.calls.push(a);
    }
  });

}));

然后你可以按照你想要的方式检查电话。请参阅this plnkr以帮助您入门。