Protractor is a framework to test Angular applications. It runs tests against your application in a browser, like Chrome or Firefox. You can use it for end-to-end testing but it’s is also possible to mock the backend services. In this blog we focus on the last option: mocking the backend services. There is a lot of information available on this topic on the internet but a lot of this information is outdated. Even the AngularJS website does not explain in detail how to mock your backend services.

This blog will explain how to setup a Protractor test and how to mock your backend services with the ngMockE2E module of AngularJS. There are also a lot of external frameworks on Github available but I think there is no reason to use these frameworks.

First, you have to make sure you have installed Protractor correctly. After that you have to make sure you load the angular-mocks javascript file (angular-test.js) in your application.

When testing an application we don’t want to mix test code and real application code. Luckily Protractor is able to load mock modules in your Angular application from your test code. See line 10 in the following test. (I have used Jasmine to write this test)

1:  describe('view1', function() {
2:   beforeEach(function() {
3:    var mock = function() {
4:     var module = angular.module('myMockApp', ['ngMockE2E']);
5:$httpBackend) {
6:      $httpBackend.whenGET('http://localhost:8080/test').respond({ dummy: 'test'});
7:      $httpBackend.whenGET('view1/view1.html').passThrough();
8:     });
9:    };
10:    browser.addMockModule('myMockApp', mock);
11:    browser.get('index.html#/view1');
12:   });
13:   afterEach(function(){
14:    browser.clearMockModules();
15:   });
16:   it('should render view1 when user navigates to /view1', function() {
17:    // expectations
18:   });
19:  });

After each test we clean up the mocks because we don’t want to influence other test scripts. (Line 14)

How does it work?

The following diagram from the Protractor documentation explains a lot.

In our test script we got a browser object which can instruct the real browser. So what happens if we call the function addMockModule?

  1. There will be a HTTP call from the NodeJs test to the Selenium server
  2. The Selenium server will forward the request to the browser and AngularJS will add the module to module list. The context of this module is the browser!

Synchronous communication

The example described above failed to work initially for our application. The mock was loaded but the Angular application was already started and looking for the view template. The result was a HTTP 404. The underlying problem was the configuration of our i18nextProvider. This module was configured to load the language files synchronously and causes latency on the main thread of our application.

If you have any questions or remarks please add a comment to this post.