Breaking down AngularJS Unit Testing

A strong suite of unit tests is incredibly valuable to any application. Through unit testing, confidence in your code (now and through refactorings) dramatically increases and a living documentation for your code base is born. Luckily for us, Angular was developed with testability at the forefront. Unfortunately for us, the formatting can be a bit strange and offer a barrier to those first getting into Angular unit testing. In this post I hope to clarify the common steps needed to get started constructing a reliable test suite.

The Code: Plunker

The Testing Framework
Angular tests are best written using the Jasmine Testing Framework. Jasmine allows you to write BDD (Behavior Driven Development) style tests (‘specs’ in BDD terms) that clearly define user stories. This is a stark contrast to more classical unit testing which defines methods, expected results, and is typically unreadable by a non-technical subscriber. Angular also provides a custom mocking framework to be used while testing.
The Setup
Using the beforeEach and afterEach properties, Jasmine provides a way to encapsulate common setup and breakdown required for each test. As the name implies, each beforeEach is run once before each test while afterEach blocks are run once after every test is complete. This is similar to Setup and Teardown (or similarly named) functionality in other frameworks. When testing Angular, you will always use one or more beforeEach steps and often use a afterEach step, particularly when testing controllers with services. So how does this look?
First Step: Specify Your Module
Per Jasmine convention, you will first describe what you are testing (controller, service, directive, etc.) then define the Angular module to which it belongs within the first beforeEach block. In this example I am testing the ‘simpleController’ in the ‘ngTestingApp’ module.

Be sure to declare any variables you will be using in your tests at the top of the describe block. It is important to note that if you intend to inject mocks or spy’s using the Angular $provide service these will be injected during this step.

Second Step: Assign Your Variables
Remember those variables we declared up top? Now it’s time to put them to work using Angular’s injector. Declare another beforeEach block and call Angular’s inject function passing in the needed dependencies.

The underscores used in the inject function will be stripped and the real services provided. This allows you to use clean variable names such as $rootScope and $controller throughout your suite.
Third Step: Set Up Your Controller (or service…etc.)
Assuming you are testing a controller you will need one more beforeEach block.

In this example I am using ‘Controller As’ syntax but when using a classic controller with $scope simply declare the controller name. That’s it, You are now ready to write your Angular tests!
Last Step: Write Your Tests
Your tests (or specs) are specified using the Jasmine ‘it’ keyword. These tests should be readable to the non-technical user and should describe the functionality of the object that you are testing. An small example of a simple controller that adds and subtracts number can be seen below.

Putting It Together
The entire controller:

Testing the controller:

Although the syntax is a bit funky, once you get the hang of it writing tests in Angular is actually quite simple. For the complete code + an example of how to test a controller with service dependencies using $httpBackend (inspired by Scott Allen’s post) please check out my Plunker. Until next time, happy coding!

Next ArticleAngular 'Controller As' Communication Utilizing Services