Unit Testing MobileCaddy Apps

This document should cover approaches and examples to unit testing MobileCaddy applications

Versions

This document should apply to all versions of MobileCaddy package and supporting libraries.

Concept

Unit testing is an important tool in the developer’s chest. Adopting a Test Driven Development approach can heavily help in identifying failure scenarios and aid project structure, whilst simultaneously increasing confidence in your codes resilience.

Code structure – Controllers vs Services

Despite what many getting started guides for AngularJS and Ionicv1 say, AngularJS controllers should be be code-light. In most scenarios Services should contain the bulk of logic within your applications. As well as being best practice in regards to separation of concerns, it also benefits the developer when it comes to writing unit tests. Unit testing controllers isn’t so straightforward, whereas services are much easier to test.

Configuring and Running Unit Tests

MobileCaddy shell/starter apps come with a framework for unit-testing already in place, and utilise Karma and Jasmine, for running and writing your tests respectively.

The karma configuration is placed in the ~/tests/my.conf.js file, which shouldn’t need any changes unless you pull in 3rd party libraries into your project.

Karma can be run with the following command; this will run a single test run, by default, but this option can be modified in the Karma configuration file.

Writing Tests

Each Angular Service should have it’s own test spec file, and this should be located in the ~/tests/Services directory, and be sensibly named.

To start let’s say we have a service as follows;

At the most basic level, a test spec could be like this, showing a single test suite, with a single test case (spec), which in turn has a single assertion in place.

For us to test out Angular Service though, we need to make sure our suite has access to the dependant service, so we add some injection code. We’ll also update our example to add a test in for our getOne function.

If we run our test now, we will see that our MyService is tested with our grunt task that we get output that includes the following, and we can see our service was tested, with all tests passing and with 100% coverage (for our service);

Mocking MobileCaddy Libraries

It is possible to mock the calls MobileCaddy libraries – such as devUtils – in you test specs. Let’s say we have increased our MyService service to make use of the devUtils, as follows;

my.service.js

Things to note in our test code is that since we are using asynchronous calls we are passing a done function into our specs, and then calling this upon completion. We also want to make sure that we are testing rejections from our devUtils promises, to make sure that they are not just being dropped by our services.

myService.tests.js

It is possible to mock the calls to other services within your application, in a similar fashion. For example you could mock calls to the SyncService also.

Bitbucket Pipelines Integration

To enable Bitbucket pipelines so that the unit tests are run on each commit first enable pipelines on your repository. Second, create a bitbutcket-pipelines.yml file that contains this content;

Coverage Options

Coverage information can be output into local html files, rather than standard text form. This is useful during local test writing, as it gives you information on the lines of code that have been covered.

To achieve this comment out the following lines from the ~/tests/my.conf.js

With this commented out, when you run the unit tests you will get files saved under the ~/tests/coverage directory. Open the index file here and you can dig down through your services.

unit-test-coverage

Troubleshooting

  • “Error: Timeout – Async callback was not invoked within timeout” – Seeing this error can often be the case when your test spec is calling asynchronous functions. The handling of asynchronous call flow requires the done() function to be passed and called within your spec. See the examples above.

References