Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mock $httpBackend in angular e2e tests

Does anyone have an idea how to mock $httpBackend in angular e2e tests? The idea is stubbing XHR requests while running tests on travis-ci. I'm using karma to proxy assets and partials from my rails app running on travis. I want to do acceptance testing without real DB queries.

Here is part of my karma config file:

...
files = [
  MOCHA,
  MOCHA_ADAPTER,

  'spec/javascripts/support/angular-scenario.js',
  ANGULAR_SCENARIO_ADAPTER,

  'spec/javascripts/support/angular-mocks.js',
  'spec/javascripts/e2e/**/*_spec.*'
];
...

proxies = {
  '/app': 'http://localhost:3000/',
  '/assets': 'http://localhost:3000/assets/'
};
...

Here is part of my spec file:

beforeEach(inject(function($injector){
  browser().navigateTo('/app');
}));

it('should do smth', inject(function($rootScope, $injector){
  input('<model name>').enter('smth');
  //this is the point where I want to stub real http query
  pause();
}));

I have tried to receive $httpBackend service through $injector:

$injector.get('$httpBackend')

But this is not the one that is used inside iframe where my tests run.

The next try I made was using angular.scenario.dsl, here is code samle:

angular.scenario.dsl('mockHttpGet', function(){
  return function(path, fakeResponse){
    return this.addFutureAction("Mocking response", function($window, $document, done) {
      // I have access to window and document instances 
      // from iframe where my tests run here
      var $httpBackend =  $document.injector().get(['$httpBackend']);
      $httpBackend.expectGET(path).respond(fakeResponse)
      done(null);
    });
  };
});

Usage example:

it('should do smth', inject(function($rootScope, $injector){
  mockHttpGet('<path>', { /* fake data */ });
  input('search.name').enter('mow');
  pause();
}));

This leads to following error:

<$httpBackend listing>  has no method 'expectGET'

So, at this point I have no idea of next step. Have anyone tried doing something like this, is this type of stubbing really possible?

like image 341
Alexander Zhukov Avatar asked May 29 '13 06:05

Alexander Zhukov


1 Answers

If you are really trying to mock out the backend in a E2E test (these tests are called Scenarios, while Specs are used for unit testing) then this is what I did in a project I was working on earlier.

The application I was testing was called studentsApp. It was an application to search for students by querying a REST api. I wanted to test the application without actually querying that api.

I created a E2E application called studentsAppDev that I inject studentsApp and ngMockE2E into. There I define what calls the mockBackend should expect and what data to return. The following is an example of my studentsAppDev file:

"use strict";

// This application is to mock out the backend. 
var studentsAppDev = angular.module('studentsAppDev', ['studentsApp', 'ngMockE2E']);
studentsAppDev.run(function ($httpBackend) {

    // Allow all calls not to the API to pass through normally
    $httpBackend.whenGET('students/index.html').passThrough();

    var baseApiUrl = 'http://localhost:19357/api/v1/';
    var axelStudent = {
        Education: [{...}],
        Person: {...}
    };
    var femaleStudent = {
        Education: [{...}],
        Person: {...}
    };
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&')
        .respond([axelStudent, femaleStudent]);
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axel&')    
        .respond([axelStudent, femaleStudent]);
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=1&')
        .respond([axelStudent]);
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=2&')
        .respond([femaleStudent]);
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=3&')    
        .respond([]);

    ...

    $httpBackend.whenGET(baseApiUrl + 'departments/?teachingOnly=true')
        .respond([...]);
    $httpBackend.whenGET(baseApiUrl + 'majors?organization=RU').respond([...]);
});

Then, I have a first step in my Jenkins CI server to replace the studentsApp with studentsAppDev and add a reference to angular-mocks.js in the main index.html file.

like image 89
Axel Örn Sigurðsson Avatar answered Nov 20 '22 00:11

Axel Örn Sigurðsson