I have a controller with an event listener in my Angular app, defined as follows.
angular.module('test').controller('TestCtrl', function($rootScope, $scope, testService) {
[...]
$scope.$on("myEvent", function(args, value) {
testService.doStuff(value);
});
});
This works perfectly in the app itself. However, when I try to unit test the functionality of the controller (using Jasmine and Karma), each test method throws the following error:
TypeError: $scope.$on is not a function in [...]/testController.js
I create the controller in my test methods as follows.
it('does stuff', inject(function($rootScope, $controller, testService) {
var scope = $rootScope.$new;
$controller('TestCtrl', {
$scope : scope
});
[...]
}));
I can get around the problem by changing my controller to use rootScope
instead:
$rootScope.$on(...)
but then of course the app doesn't work anymore as expected. I can also get rid of the error by introducing the $on
method in my test code:
var scope = $rootScope.$new;
scope.$on = function() {};
but mocking the listener like this kind of defeats the purpose of testing my real code.
Why doesn't the test code find the $on
method of the scope
? (But finds it on rootScope
, still...)
There must be something fundamental that I'm missing here but I haven't been able to figure it out even after lots of googling and reading the Angular source code.
Editor’s note: This tutorial was last updated on December 31, 2020. In this Angular unit testing tutorial, we’ll demonstrate how to build a simple Angular app and then walk through the unit testing process step by step with examples.
With AngularJS, there is no excuse for not testing. Separation of Concerns Unit testing, as the name implies, is about testing individual units of code. Unit tests try to answer questions such as "Did I think about the logic correctly?"
For this reason we feel very strongly that any code written in JavaScript needs to come with a strong set of tests. We have built many features into AngularJS which make testing your AngularJS applications easy. With AngularJS, there is no excuse for not testing. Separation of Concerns
There are two types of Angular testing: Unit testing is the process of testing small, isolated pieces of code. Also known as isolated testing, unit tests do not use external resources, such as the network or a database
$rootScope.$new
is a function. You need to invoke it ($rootScope.$new()
):
it('does stuff', inject(function($rootScope, $controller, testService) {
var scope = $rootScope.$new();
$controller('TestCtrl', {
$scope : scope
});
[...]
}));
Example plunk: http://plnkr.co/edit/t1x62msmOQDkNItGzcp9?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With