Testing AngularJS Applications – Part 1
Author: Sabbir Siddiqui
Technical Lead
Java / JavaScript / Front end systems / Healthcare / Data Science / NLP

- “Backend has a lot of unit tests, should be enough”
- “How do you test the frontend anyway?”
- “Testing frontend code? Sounds messy. Ugh Javascript though”
We have probably heard these words while working on a project that involves frontend development. I’ve worked on a few AngularJS applications and some Ionic applications (so basically a bunch of AngularJS applications) before joining Infolytx. Those standalone applications were rapidly built, and writing unit tests was seemingly far and beyond my scope of work. It’s very easy to say – “If the UI ain’t broke, don’t fix it!” (Please don’t quote me out of context on this).
The myriad of JS frameworks being used today are accompanied by robust testing frameworks – giving us the ability to follow agile practices such as Test Driven Development (TDD), and leaving us with no excuse to ignore testing frontend code.
This blog post is the first of a multi-part series that describes how to test AngularJS applications, as well as some quick tips on testing in general. This post assumes that you have some basic knowledge of writing AngularJS controllers and JavaScript functions, but have not looked into testing as much.
The most popular framework for unit tests in AngularJS is using Jasmine with Karma.
“Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests.” – jasmine.github.io
In other words, Jasmine provides libraries for assertions, spies, mocks etc. and the tools you need for writing unit tests.
Karma is the runner and provides an environment in which the unit tests run. Karma was created by the AngularJS team, to make developers’ lives easier.
To learn how to setup Jasmine and Karma, you can follow these links:
- https://daveceddia.com/testing-angular-part-1-karma-setup/
- http://www.bradoncode.com/blog/2015/05/19/karma-angularjs-testing/
In terms of folder structure, I like to keep my tests in a separate folder called ‘tests’, with the same sub-folder structure as my app code. For example:
What does an AngularJS unit test look like?
You’re done! Now go do the thing.
Not quite. I laud your curiosity for making it this far. Let’s briefly go over what we saw in that dark themed code screenshot (team dark-theme all the wayyyy).
- describe
A suite of tests; this can be used to group unit tests together. It can be useful to have common variables or objects for multiple unit tests, which the describe function scope can contain.
- it
This is a single unit test, and where the assertions are run. The above example uses a simple it string (test identifier), but the convention I like to follow for naming tests is:
> It “should do this, given these conditions”
- expect
This comes from the Jasmine library of assertions, and has a myriad of ‘toBe’ methods to test value equality, function calls, etc.
Testing Angular Controllers
I can proudly declare that I’ve written AngularJS code using the TDD approach. Who does that?! (teams who follow best practices do) Literally nobody does! (seriously, it produces better code so you should do it).

Let’s look at two simple functions that we want to write using TDD.

The first will be a function that adds two numbers together. Simple enough? Think again! In the spirit of TDD, let’s write a test to make sure the function exists. This test will obviously fail, because the function doesn’t exist yet. This will give you an opportunity to think about what the function name should be and what it will do.
Take some time to study the code below.
You might notice some new keywords in the code above.
- beforeEach
This segment runs before each it segment, and can be used to set up common variables that you will use for each test. Common variables will vary depending on the test, but examples include mock data, mock functions, the mock scope, etc.
- $injector
This is a very handy AngularJS service for testing purposes. As demonstrated in the code snapshot, the injector.get method can be used to get instances of Angular services, and your own services and controllers, so that you can either mock them or observe their behavior during testing. Read more on the injector service here.
After that glob of code, that single it segment will test whether your SampleController has a getSum function. The inject bit is how the injector service is used to get instances of your controllers, providers and services from your angular module.
Currently the function does not exist, so this test will fail. To pass the test, we can write an empty function, but with an improved name because I thought long and hard about this. This should also make sure that you’re paying attention.
The name makes more sense now. First we test whether the function exists, then we test whether the function returns the expected result.
Let’s expect this function to do as it says, by adding another ‘it’ segment below the toBeDefined check.
Now that you’ve got another failing test, let’s make it pass with some passable code.
This might pass for working code, but there are more things to consider.
For example,
- What happens when a null input is given for either of the two parameters?
- What happens when one of the parameters is undefined?
- What happens when either of the parameters is not a number?
As demonstrated before, write out test cases that would fail due to those scenarios, and make them pass with minimal code.
Read more about the idiosyncrasies of ‘null’ and ‘undefined’ in Javascript at codeburst.io.
The second function will deal with adding items to an array. Similarly, we would write a test to check if the function is already defined, then write an empty function to make it pass.
Let’s do a basic implementation to make the second ‘it’ pass.
Does it pass? Yes. Is there more work to do? Definitely. To make your code more robust, consider the scenarios presented earlier; what if the item is null, or undefined? Or if there are constraints for the item type in the array, then those scenarios should be considered as well.
– me
A quick tip before wrapping up – robust code should be built on robust tests. For example, we are happy with testing whether the item has been added to the list as shown above, by checking the number of items in the list which is expected to increase. What I always try to do is to not only make the unit test pass with a basic expectation, but to ensure that I know exactly what I am expecting. For this example, in addition to testing that an item has been added to the list, we can also ensure that the specific intended item is added – as shown in the 2nd last line:
Stay tuned for more on Testing AngularJS Applications. Next, we will look more closely at mocking dependencies, and testing more complex controller functions. Thanks for reading!










