Mock $ httpBackend in angular e2e tests

Does anyone have an idea how to mock $ httpBackend in angular e2e tests? The idea is to skip XHR requests during travis-ci tests. I use karma for proxy assets and partial applications from my rails application running on travis. I want to conduct acceptance testing without real database queries.

Here is part of my karma configuration 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 tried to get the $ httpBackend service through $ injector:

 $injector.get('$httpBackend') 

But this is not the one used inside the iframe where my tests are executed.

In the next attempt, I used angular.scenario.dsl, here is the samle code:

 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 results in the following error:

 <$httpBackend listing> has no method 'expectGET' 

So, at the moment, I have no idea about the next step. Has anyone tried to do something like this, is this type of stubbing really possible?

+8
angularjs mocking karma-runner acceptance-testing end-to-end
source share
3 answers

If you are really trying to make fun of the backend in the E2E test (these tests are called Scenarios, and Specs are used for unit testing), then this is what I did in the project that I worked on before.

The application I tested was called studentsApp . It was an application for finding students by querying the REST api. I wanted to test the application without requesting an api.

I created an E2E application called studentsAppDev , which I insert studentsApp and ngMockE2E into. There I determine what calls mockBackend should expect and what data should be returned. 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 the first step on my Jenkins CI server to replace studentsApp with studentsAppDev and add a link to angular-mocks.js in the main index.html file.

+7
source

Retrieving your database is an important step in creating a complex Angular application. This allows testing without access to the backend, you don’t check things twice, and there are fewer dependencies to worry about.

Angular Multimocks is an easy way to test how your application behaves with various API responses.

It allows you to define mock API response sets for different scenarios as JSON files.

It also makes it easy to modify scripts. It does this, allowing you to compose "scripts" from different layout files.

How to add it to your application

After adding the necessary files to your page, just add scenario as a function of your application:

 angular .module('yourAppNameHere', ['scenario']) // Your existing code here... 

Once you have added this to your application, you can start creating mocks for API calls.

Let's say your application calls the following API call:

 $http.get('/games').then(function (response) { $scope.games = response.data.games; }); 

You can create a default mock file:

someGames.json example

 { "httpMethod": "GET", "statusCode": 200, "uri": "/games", "response": { "games": [{"name": "Legend of Zelda"}] } } 

When the application loads, calls to /games return 200 and {"games": [{"name": "Legend of Zelda"}]}

Now let's say that you want to return a different answer for the same API call, you can put the application in a different script by changing the URL, for example. ?scenario=no-games

In the no-games script, you can use a different file layout, let's say this:

noGames.json example

 { "httpMethod": "GET", "statusCode": 200, "uri": "/games", "response": { "games": [] } } 

Now, when you download the application, calls to /games return 200 and {"games": []}

Scripts consist of various JSON mocks in a manifest like this:

 { "_default": [ "games/someGames.json" ], "no-games": [ "games/noGames.json" ] } 

You can then exclude the fake files and split the scenario dependency in your production application.

+1
source

This is more like unit / spec testing. Generally speaking, you should use mocks in unit / spec tests, and not in e2e / integration tests. Basically, think of e2e tests as a statement of expectations in a mostly integrated application ... bullying about the form of defeat, the purpose of testing e2e. In fact, I'm not sure how Karam inserted angular -mocks.js into a running application.

A spectral test might look something like this ...

 describe('Controller: MainCtrl', function () { 'use strict'; beforeEach(module('App.main-ctrl')); var MainCtrl, scope, $httpBackend; beforeEach(inject(function ($controller, $rootScope, $injector) { $httpBackend = $injector.get('$httpBackend'); $httpBackend.when('GET', '/search/mow').respond([ {} ]); scope = $rootScope.$new(); MainCtrl = $controller('MainCtrl', { $scope: scope }); })); afterEach(function () { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); it('should search for mow', function () { scope.search = 'mow'; $httpBackend.flush(); expect(scope.accounts.length).toBe(1); }); }); 
0
source

All Articles