业力:模块化请求测试的麻烦
Karma: trouble modularizing testing of requests
这是我正在测试的控制器:
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();
});
});
当前失败:
它要我在第二个 it
块中有一个 $httpBackend.expectGET('/users')
。我不想那样做。对我来说,如果每个 it
块测试一个单独的东西,它似乎更加模块化和有条理。
1) 我该怎么办?
2) 为什么我会收到 $digest already in progress
错误?
- 你是对的,每个
it
应该测试一个单独的东西。 it
块是单独的测试,它们不(不应该)相互依赖。第二个测试创建一个新的控制器实例,它会尝试立即加载用户。即使您对这里的这个请求不感兴趣,您仍然需要设置处理它的 mock。您也可以使用 .when(...).respond(...)
形式代替 expect
.
编辑: 一种使它更好的方法是将 GET 的模拟移动到 beforeEach
作为 $httpBackend.expectGET('/users').respond(users)
。这样,第一个 GET 的模拟将适用于所有 it
测试,因此在测试其他内容时,您无需担心。至于第一个it
,也许只做expect(adminController.users).toEqual(users)
就够了。 (对于控制器如何获取用户没有明确的期望,只有值——但这显然来自 GET,因此覆盖范围基本相同。)
这是我正在测试的控制器:
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();
});
});
当前失败:
它要我在第二个 it
块中有一个 $httpBackend.expectGET('/users')
。我不想那样做。对我来说,如果每个 it
块测试一个单独的东西,它似乎更加模块化和有条理。
1) 我该怎么办?
2) 为什么我会收到 $digest already in progress
错误?
- 你是对的,每个
it
应该测试一个单独的东西。it
块是单独的测试,它们不(不应该)相互依赖。第二个测试创建一个新的控制器实例,它会尝试立即加载用户。即使您对这里的这个请求不感兴趣,您仍然需要设置处理它的 mock。您也可以使用.when(...).respond(...)
形式代替expect
.
编辑: 一种使它更好的方法是将 GET 的模拟移动到 beforeEach
作为 $httpBackend.expectGET('/users').respond(users)
。这样,第一个 GET 的模拟将适用于所有 it
测试,因此在测试其他内容时,您无需担心。至于第一个it
,也许只做expect(adminController.users).toEqual(users)
就够了。 (对于控制器如何获取用户没有明确的期望,只有值——但这显然来自 GET,因此覆盖范围基本相同。)