UI router interacts with $ httpbackend unit test, angular js

This is a controller with a send function:

$scope.submit = function(){ $http.post('/api/project', $scope.project) .success(function(data, status){ $modalInstance.dismiss(true); }) .error(function(data){ console.log(data); }) } } 

This is my test.

 it('should make a post to /api/project on submit and close the modal on success', function() { scope.submit(); $httpBackend.expectPOST('/api/project').respond(200, 'test'); $httpBackend.flush(); expect(modalInstance.dismiss).toHaveBeenCalledWith(true); }); 

The error I get is:

 Error: Unexpected request: GET views/appBar.html 

views / appBar.html is my url template:

  .state('project', { url: '/', templateUrl:'views/appBar.html', controller: 'ProjectsCtrl' }) 

So somehow ui-router does my $ httpBackend item for this instead of my send function. I have the same problem in all my tests using $ httpBackend.

Is there any solution for this?

+44
javascript angularjs angular-ui-router karma-runner angular-ui
May 14 '14 at 12:52
source share
5 answers

Take this sense https://gist.github.com/wilsonwc/8358542

 angular.module('stateMock',[]); angular.module('stateMock').service("$state", function($q){ this.expectedTransitions = []; this.transitionTo = function(stateName){ if(this.expectedTransitions.length > 0){ var expectedState = this.expectedTransitions.shift(); if(expectedState !== stateName){ throw Error("Expected transition to state: " + expectedState + " but transitioned to " + stateName ); } }else{ throw Error("No more transitions were expected! Tried to transition to "+ stateName ); } console.log("Mock transition to: " + stateName); var deferred = $q.defer(); var promise = deferred.promise; deferred.resolve(); return promise; } this.go = this.transitionTo; this.expectTransitionTo = function(stateName){ this.expectedTransitions.push(stateName); } this.ensureAllTransitionsHappened = function(){ if(this.expectedTransitions.length > 0){ throw Error("Not all transitions happened!"); } } }); 

Add it to a file called stateMock in the test / mock folder, include this file in your karma configuration, if it has not already been selected.

The setup before your test should look something like this:

 beforeEach(module('stateMock')); // Initialize the controller and a mock scope beforeEach(inject(function ($state //other vars as needed) { state = $state; //initialize other stuff } 

Then in your test you should add

 state.expectTransitionTo('project'); 
+48
May 15 '14 at 5:47
source

This Github question about Unit Testing UI Router explains in more detail what is happening.

The problem is that $httpBackend.flush() triggers the broadcast, which then triggers the otherwise stateProvider case.

A simple solution might be the following setup, which is mentioned in the @darinclark article in the Github article mentioned above. This is true if you do not need to check the state of transitions. Otherwise, check out @rosswil's answer , which is inspired by @ Vratislav's Github Reply .

 beforeEach(module(function ($urlRouterProvider) { $urlRouterProvider.otherwise(function(){return false;}); })); 

EDITED

Thanks to Chris T for reporting this in the comments, it seems, after v0.2.14? the best way to do this is to use

 beforeEach(module(function($urlRouterProvider) { $urlRouterProvider.deferIntercept(); })); 
+38
Oct 28 '14 at 16:11
source

If you do not want to add gist files, as indicated in the correct solution, you can add the when condition to your $ httpBackend to ignore GET petitions of the kind like this:

 $httpBackend.when("GET", function (url) { // This condition works for my needs, but maybe you need to improve it return url.indexOf(".tpl.html") !== -1; }).passThrough(); 
+3
Apr 22 '15 at 10:29
source

I have the same error you commented about, after the call service they ask me about the url of another ui route.

To solve the call problem, otherwise the ui-route will not enter $ state in beforeach when testing. In my testing, $ state does not make sense to use it.

+2
Jul 01 '15 at 8:42
source

Move your services to your own ui.router-independent module. Your main application depends on this module. When you are testing, do not test the main application, check the module that has your services. Stateprovider will not try to change state / route, because this module does not know anything about ui.router. It worked for me.

+1
Dec 20 '14 at 11:57
source



All Articles