1

以下测试通过:

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。并说,“如果我收到那个请求,我会用 'foo' 回应”。
  5. $httpBackend.flush()说“为收到的任何请求发送定义的响应$httpBackend。”
  6. .expectGET失败是因为它没有收到它的请求(请求发生在预期之前)。
  7. .flush()抛出一个错误,因为没有什么要刷新的。

我没有得到我期望的结果,所以我上面的逻辑一定是错误的——它是什么?

4

1 回答 1

3

$http 尚未被 $httpBackend 覆盖,因此请求正常发出。

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

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

编辑

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

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

于 2015-08-10T15:52:38.163 回答