Adelin
Adelin

Reputation: 18961

Angular E2E testing with mocked httpBackend?

A hot discussion raised between me and my boss about Angular E2E testing. according to vojitajina pull request we need to run a server in order to run the e2e tests. So, running e2e test involves a real server, a real server involves DB. This makes test slow.Ok, now the question is how to test e2e without involving a real server ? is there a way to use httpBackend to and the e2e angular API where I can use browser(), element(), select(), for my tests ?

Upvotes: 4

Views: 2086

Answers (2)

Mark Nadig
Mark Nadig

Reputation: 5136

[see edit below] We use a shell script to periodically capture curl requests from our seeded test server. These responses are then returned via $httpBackend.whenGet(...).respond() to intercept and return that data.

So, in our index.html

if (document.location.hash === '#test') {
  addScript('/test/lib/angular-mocks.js');
  addScript('/test/e2e/ourTest.js');
  window.fixtures = {};
  addScript('/test/fixtures/tasks/tasks_p1.js');
  // the tasks_p1.js is generated and has "window.fixtures.tasks_p1 = ...json..."
  addScript('/test/fixtures/tasks/tasks_p2.js');
  // the tasks_p2.js is generated and has "window.fixtures.tasks_p2 = ...json..."
  addScript('/test/e2e/tasks/taskMocks.js\'><\/script>');
}

ourTest.js

angular.module('ourTestApp', ['ngMockE2E','taskMocks']).
    run(function ($httpBackend, taskMocks) {
      $httpBackend.whenGET(/views\/.*/).passThrough();
      $httpBackend.whenGET(/\/fixtures.*\//).passThrough();

      taskMocks.register();

      $httpBackend.whenGET(/.*/).passThrough();
    });

taskMocks.js

/*global angular */
angular.module('taskMocks', ['ngMockE2E']).
  factory('taskMocks', ['$httpBackend', function($httpBackend) {
  'use strict';
  return {
    register: function() {
      $httpBackend.whenGET(..regex_for_url_for_page1..).respond(window.fixtures.tasks_p1);
      $httpBackend.whenGET(..regex_for_url_for_page2..).respond(window.fixtures.tasks_p2);
    }
  };
}]);

In a few cases our data is related to the current date; e.g. "tasks for this week", so we massage the captured data in the register() method.

EDIT We now use Rosie to create factories for our mocked objects. So, no more CURLing test server for expected json responses. index.html no longer loads these ".js" fixtures and the mocks look like:

taskMocks.js

/*global angular */
angular.module('taskMocks', ['ngMockE2E']).
  factory('taskMocks', ['$httpBackend', function($httpBackend) {
  'use strict';
  var tasks_p1 = [ Factory.build('task'), Factory.build('task')], 
      tasks_p2 = [ Factory.build('task'), Factory.build('task')] 
  return {
    register: function() {
      $httpBackend.whenGET(..regex_for_url_for_page1..).respond(tasks_p1);
      $httpBackend.whenGET(..regex_for_url_for_page2..).respond(tasks_p2);
    }
  };
}]);

Upvotes: 5

EdL
EdL

Reputation: 154

To answer your question, yes there is a way to do it without involving a real server and you can use $httpBackend to mock responses in e2e tests, but it is not as straightforward as with mocking them in the unit tests. You also need to include angular-mocks.js in the index.html as well as 'ngMockE2E' in app.js.

How to mock an AJAX request?

Upvotes: -1

Related Questions