Angular Part 4–Testing AngularJS

This is the fourth in a series that starts here.  It is time now to turn our attention to testing AngularJS applications.  Over time, we’ll want to move to test-first, where we write the test and then write the code. There are many advantages to test-first, but let’s hold off on discussing them until we’re ready for that step.

Today, I’d like to discuss testing Controllers.  Controllers were introduced in the previous posting.  To make sure we’re all on the same page, let’s start with a common starting project, which you can download here.  This stripped down project has no tests in it, and has the very simple controller that we created in the previous posting.

Over time, we’ll want to modify and extend this project extensively, but for now, let’s create our first AngularJS test using Jasmine, to test the controller.

To do so, create a new file in the spec folder named expensesControllerSpec.js.  It turns out to be slightly tricky to test a controller. To do so, we’re going to create a controller constructor that will in turn create an instance of expensesController, and will pass in the needed $Scope object. The $Scope object is passed in implicitly when you use the ControllerAs method that we used to create our controller, but here we must pass it in explicitly.

In Part 2 of this series, I went over how to create a basic Jasmine test with a beforeEach section, so I won’t review that here.  We’re going to start our new test by adding a describe function,

describe(‘expensesController’, function(){

})

 

and within that we’ll add our first test of the controller,

describe(‘expensesController’, function(){

it(‘should have three expense items’, function(){

})

})

 

Before we can fill in the it function, we need to be able to create our controller. The first thing we need is a beforeEach that gets the module,

beforeEach(module(‘app’));

 

Next, we need a second beforeEach which will call the inject method to inject the controller and rootScope objects. We’ll create local variables to hold these,

describe(‘expensesController’, function(){

var $controllerConstructor;
var scope;

beforeEach(inject(function($controller, $rootScope){
$controllerConstructor = $controller;
scope = $rootScope.$new();
}));

 

We’re now ready to fill in our test with its expect statement.  Here is the complete spec file:

describe(‘expensesController’, function(){

var $controllerConstructor;
var scope;

beforeEach(module(‘app’));

beforeEach(inject(function($controller, $rootScope){
$controllerConstructor = $controller;
scope = $rootScope.$new();
}));

it(‘should have three expense items’, function(){
var ctrl = $controllerConstructor(‘expensesController’,
{$scope:scope});
expect(ctrl.expenseItems.length).toBe(3);
})

})

 

We now only need to update SpecRunner.html with the name of our newest spec file,

<!– include spec files here… –>
<script type="text/javascript"
src="spec/expensesControllerSpec.js"></script>

 

Make sure that expensesController.js is also referenced in Specrunner.html,

<!– include source files here… –>
<script type="text/javascript"
src="src/app/expensesController.js"></script>

 

If you are using WebStorm (and if not, why aren’t you??) you can right-click on SpecRunner.html and choose Open In Browser –> Default and see something  very much like this (red box added):

ExpensesControllerTest

 

That completes your first Jasmine test for AngularJS. 

It is time to think about adding a Service so that we don’t have the data hard-coded in the Controller, and we’ll do so in the next posting.

 

About the author:

Jesse Liberty is a Master Consultant for Falafel Software, a Microsoft MVP, a Telerik MVP, an author, and he creates courses for Pluralsight.    Liberty co-hosts the popular Yet Another Podcast and his blog is considered required reading. He was a Senior Evangelist for Microsoft,  a XAML Evangelist for Telerik, a Distinguished Software Engineer at AT&T; Software Architect for PBS and Vice President of Information Technology at Citibank. Jesse can be followed on twitter at @JesseLiberty

The following two tabs change content below.

Jesse Liberty

Master Consultant at Falafel Software
Jesse Liberty is a Master Consultant for Falafel Software, an author and he creates courses for Pluralsight . He is a Microsoft MVP and a Certified Xamarin Mobile Developer. Liberty hosts the popular Yet Another Podcast and his blog is considered required reading. He was a Senior Evangelist for Microsoft, , a XAML Evangelist for Telerik , Distinguished Software Engineer at AT&T; Software Architect for PBS and Vice President of Information Technology at Citibank.