Here is the controller I'm testing:
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.');
});
};
}
And my tests:
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's currently failing:
It wants me to have an $httpBackend.expectGET('/users')
in my second it
block. I don't want to do that. To me, it seems more modular and organized if each it
block tests a separate thing.
1) What should I do?
2) Why am I getting the $digest already in progress
error?
it
should test a separate thing. The it
blocks are separate tests, they don't (shouldn't) depend on each other. The second test creates a new controller instance, which in turn tries to load users immediately. Even if you're not interested in this request here, you still need to set up the mock that handles it. You can also use the .when(...).respond(...)
form instead of expect
.EDIT: One way to make this nicer would be to move the mocking of GET into a beforeEach
as $httpBackend.expectGET('/users').respond(users)
. This way, the mock for the first GET would work for all it
tests, so when testing something else, you wouldn't need to worry about it. As for the first it
, maybe it would be enough to only do expect(adminController.users).toEqual(users)
. (There would be no explicit expectation about how the controller gets the users, only about the value -- but that obviously comes from the GET, so the coverage would be essentially the same.)