$httpBackend.expect() 应该去哪里?

Where should $httpBackend.expect() go?

以下测试通过:

admin.controller.js

angular
  .module('mean-starter')
  .controller('AdminController', AdminController);

function AdminController(User, Auth, $state) {
  var vm = this;
  User
    .list()
    .success(function(data) {
      vm.users = data;
    })
    .error(function() {
      console.log('Problem getting users.');
    });

  vm.delete = function(id) {
    User
      .delete(id)
      .success(function(data) {
        if (Auth.getCurrentUser()._id === id) Auth.logout(); // deleting yourself
        else $state.reload();
      })
      .error(function() {
        console.log('Problem deleting user.');
      });
  };
}

admin.controller.spec.js

describe('AdminController', function() {
  var AdminController, $httpBackend;

  beforeEach(module('mean-starter'));
  beforeEach(module('templates'));
  beforeEach(inject(function($controller, $rootScope, _$httpBackend_) {
    $httpBackend = _$httpBackend_;
    AdminController = $controller('AdminController');
  }));

  afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('gets users', function() {
    $httpBackend
      .expectGET('/users')
      .respond('foo');
    $httpBackend.flush();
  });
});

我没想到会这样。这是我预期会发生的事情:

  1. 控制器在beforeEach中实例化。
  2. User.list() 得到 运行.
  3. $http 尚未被 $httpBackend 覆盖,因此请求正常发出。
  4. $httpBackend.expectGET('/users').respond('foo') 预计 GET /users。并说,"I'll respond with 'foo' if I get that request".
  5. $httpBackend.flush() 说 "Send out the defined responses for any of the requests that $httpBackend received."
  6. .expectGET 失败,因为它没有收到它的请求(请求发生在预期之前)。
  7. .flush() 抛出错误,因为没有要刷新的内容。

我没有得到预期的结果,所以我上面的逻辑一定有问题 - 它是什么?

The $http isn't yet overridden by $httpBackend, so the request goes out normally.

这不是一个正确的假设。 $httpBackend 在单元测试中自动使用(它是单元测试中使用的 ng-mocks 模块的一部分)。因此,无论您在单元测试代码中是否使用 $httpBackend,它都在那里并且正在处理您的代码发出的所有 $http 请求。

想一想,如果不这样做,您的单元测试可能会提出真正的请求。

编辑

对于这种情况,控制器在实例化后立即发出 HTTP 请求,我喜欢在实例化控制器之前将 $httpBackend.expectGET() 调用放在 beforeEach 块中。

我也会 flush() beforeEach 块中的后端。我认为,这清楚地表明这些请求发生在控制器启动时。这意味着我不必在每个单元测试中都做出这种期望。