业力:模块化请求测试的麻烦

时间:2015-08-08 17:09:30

标签: angularjs karma-runner httpbackend

这是我正在测试的控制器:

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.');
      });
  };
}

我的测试:

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

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

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

  it('gets users', function() {
    var users = [ 'user1', 'user2', 'user3' ];
    $httpBackend
      .expectGET('/users')
      .respond(users);
    var adminController = createController();
    $httpBackend.flush();
    expect(adminController.users).toEqual(users);
  });

  it('has a method that deletes users', function() {
    $httpBackend.expectDELETE('/users/1').respond();
    $httpBackend.expectGET('/current-user').respond();
    $httpBackend.expectGET('/logout').respond();
    var adminController = createController();
    adminController.delete(1);
    $httpBackend.flush();
  });
});

目前失败了:

enter image description here

它要我在我的第二个$httpBackend.expectGET('/users')区块中有一个it。我不想那样做。对我来说,如果每个it块测试一个单独的东西,它似乎更模块化和有条理。

1)我该怎么办?

2)为什么我收到$digest already in progress错误?

1 个答案:

答案 0 :(得分:1)

  1. 你是对的,每个it应该测试一个单独的东西。 it块是单独的测试,它们不(不应该)相互依赖。第二个测试创建一个新的控制器实例,该实例又尝试立即加载用户。即使你在这里对这个请求不感兴趣,你仍然需要设置处理它的模拟。您也可以使用.when(...).respond(...)表单代替expect
  2. 编辑:提高效率的一种方法是将GET的模拟转换为beforeEach $httpBackend.expectGET('/users').respond(users)。这样,第一个GET的模拟将适用于所有it测试,因此在测试其他内容时,您不必担心它。至于第一个it,也许只做expect(adminController.users).toEqual(users)就足够了。 (没有明确的期望控制器如何获得用户,只有价值 - 但显然来自GET,所以覆盖范围基本相同。)

    1. 可能是这样的:https://github.com/angular/angular.js/pull/6522