Reputation: 1764
I am trying to test my AngularJS
controller function using Jasmine
. However, I am getting TypeError: undefined is not a function
.
This is what the test looks like:
describe('BoardController', function() {
beforeEach(module('examtesting'));
var BoardController;
beforeEach(inject(function($rootScope, $controller) {
var scope = $rootScope.$new();
BoardController = $controller('BoardController', {
$scope: scope,
board: null,
BoardService: null
});
}));
it ("should toggle create_active", function() {
var category = { create_active: false }
BoardController.toggleCreateActive(category);
expect(category.create_active).toBe(true);
});
});
And here's the function I am trying to test:
$scope.toggleCreateActive = function(category) {
category.create_active = !category.create_active;
}
What am I doing wrong?
Upvotes: 1
Views: 2226
Reputation: 1797
When you use $scope, all your model is on scope, and the controller is just the controller...
Testing controller with controllerAs
After we’ve seen how to test a service, let’s talk about testing a controller.
function MyController(MyService) {
this.greetUpperCase = function(name) {
return MyService.greet(name).toUpperCase();
}
}
We’d like angular’s DI to inject an instance of our controller to our test, but controllers are not singltons as services.
Therefore, we will:
inject the $controller service use it to instance a controller for us
var $controller;
beforeEach(module('MyModule'));
beforeEach(inject(function(_$controller_) {
$controller = _$controller_; })
);
it('test greetUpperCase()', function() {
var ctrl = $controller('MyController');
expect(ctrl.greetUpperCase('bob')).toBe('HELLO BOB');
});
https://jsfiddle.net/ronapelbaum/tcmsw688/
Testing controller with $scope
Now, if you’re still workng with $scope:
function MyController($scope, MyService) {
$scope.greetUpperCase = function(name) {
return MyService.greet(name).toUpperCase();
}
}
Basically, when you’re working with $scope, you don’t really care about the controller itself, since it’s doing everything on it’s scope.
So, we will need to:
inject $rootScope create a new scope inject it to a new controller test the $scope
it('test greetUpperCase()', function() {
var myScope = $rootScope.$new();
$controller('MyController', {
$scope: myScope
});
expect(myScope .greetUpperCase('bob')).toBe('HELLO BOB');
});
https://jsfiddle.net/ronapelbaum/pkhaxmdg/
Upvotes: -1
Reputation: 2337
This should work:
describe('BoardController', function() {
beforeEach(module('examtesting'));
var createController, scope;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
createController = function() {
return $controller('BoardController', {
$scope: scope,
board: null,
BoardService: null
});
};
}));
it ("should toggle create_active", function() {
var category = { create_active: false },
controller = createController();
scope.toggleCreateActive(category);
expect(category.create_active).toBe(true);
});
});
Upvotes: 2
Reputation: 2935
Like it says in the last listing toggleCreateActive is a function on the $scope. You cannot reference it as BoardController.toggleCreateActive. Instead make the scope var available for tests (move the declaration out of beforeEach) and call scope.toggleCreateActive().
Upvotes: 3