Cleaner and maintainable object mocking in unit testing through angular modules

** Prior knowledge of unit testing angular apps with Jasmine and Karma is required to understand this post.


Modularity in Angular allows us to unit tests the pieces of application with ease. One can easily mock out services and objects and can unit test the angular component (service, controller, filter etc). But there are objects that need to be mocked out in more than one unit test and sometimes they can be big making the test file look really ugly. For instance, the $modal service can be used a lot in the application and we need to test our apps behavior every time a modal opens or closes. So we will need to mock the $modal service in each unit test and here is one way of doing it:

Unit test

Unit test

In the above example, the code highlighted by the red box is a very comprehensive mocked instance and promise of the $modal service of Angular. It is so often used that it is cumbersome to make these two variables in each test file and since it takes a lot of vertical space, it is not readable at all. How cool it would be if I could make it look like this …

Want to achieve unit test

Want to achieve unit test

It is pretty much possible and here is how …

Mock file

Mock file

Create a new directory under tests. You can name it anything; I have named it as ‘mocks’ and then add a new file under that directory and name it as you like; I have named it as ‘FPMocks.js’. This file would contain a module in which you can define factories, values, constants. An example of a factory is shown below.

FPMocks.js

FPMocks.js

This factory returns an object which contains a mocked object for promise returned by a modal and modal instance which is injected into the modal controller.
Now we need to tell karma to load this file when running our tests through the karma.conf.js

Karma config

Karma config

Please make sure you pay attention to the position of the file in the files array. We want to load this file before any of the tests are loaded on the browser.

Once we have configured karma to use our file, we can add this module (FPMocks) to our test file and inject its service ($modalMock) into our beforeEach function like this …

Rewrite unit tests with FPMocks

Rewrite unit tests with FPMocks

Rewrite unit tests with FPMocks

Rewrite unit tests with FPMocks

Now, our spy will always return the promise from the $modalMock service. You can easily call close() ordismiss() in your tests and it will behave the exact same way as it does in the controllers and services in your app making it easier to test your code if the modal is resolved or rejected.

Taking this approach provides us with the following benefits:

  • Cleaner and more readable test files

Our tests/specs look a lot cleaner and are easier on the eyes.

  • Reusable code

Using Angular module makes this piece of code reusable. It is as simple as a service injection and requires very little, and I mean very little configuration. One can always pull it to other projects as well.

  • Code is scale-able and maintainable

Since my mocks are at one place, it is easier to update them if the requirement or the API changes at some point in the future. Going and editing each file is more error prone and tiresome.


You can add as many services, constants, values, factories to this module and they will simply become injectable in the unit tests.

Any questions or suggestions are welcome.

Thanks

Advertisements

3 thoughts on “Cleaner and maintainable object mocking in unit testing through angular modules

  1. Pingback: Javascript Testing – Clean object mocking through JSON files | Prog-Blogs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s