I am trying to test a service which is using $http
 var APIClient = function($http) {      this.send = function(data) {          $http({              method: data.method,              url: data.url,              headers: data.headers,              data: data.data          }).success(function(response, status) {              data.success(response, status);          }).error(function(response, status) {              data.error(response, status);          });      }  }   angular.module('api.client', []).factory('APIClient', ['$http'      function($http) {          var client = new APIClient($http);           return {              send: function(data) {                  return client.send(data);              },          }       }  ]);   And the test
  describe('send', function() {        var apiClient, $httpBackend;        beforeEach(module('compare'));        beforeEach(inject(function($injector) {           $httpBackend = $injector.get('$httpBackend');           apiClient = $injector.get('APIClient');       }));        it('Should check if send() exists', function() {           expect(apiClient.send).toBeDefined();       });        it('Should send GET request', function(done) {           var url = '/';            $httpBackend.expect('GET', url).respond({});            apiClient.send({               url: url,               success: function(data, status) {                   console.log(status);                   done();               },               error: function(data, status) {                   console.log(status);                   done();               }           });            $httpBackend.flush();       });   });   But I always have this error
PhantomJS 1.9.8 (Mac OS X) send Should send GET request FAILED         Error: Unexpected request: GET templates/test.html         Expected GET /   The expected url is always the last state in my app.js In this case 
// Ionic Starter App  // angular.module is a global place for creating, registering and retrieving Angular modules // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.services' is found in services.js // 'starter.controllers' is found in controllers.js  angular.module('compare',     [         'ionic',         'manager.user',         'api.client',         'api.user',         'api.compare',         'user.controllers',         'test.controllers'     ] )      .run(function ($ionicPlatform) {         $ionicPlatform.ready(function () {             // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard             // for form inputs)             if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {                 cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);             }             if (window.StatusBar) {                 // org.apache.cordova.statusbar required                 StatusBar.styleLightContent();             }         });     })      .config(function ($stateProvider, $urlRouterProvider) {          // Ionic uses AngularUI Router which uses the concept of states         // Learn more here: https://github.com/angular-ui/ui-router         // Set up the various states which the app can be in.         // Each state's controller can be found in controllers.js         $stateProvider              // setup an abstract state for the tabs directive             .state('tab', {                 url: "/tab",                 abstract: true,                 templateUrl: "templates/tabs.html"             })              // Each tab has its own nav history stack:              .state('tab.dash', {                 url: '/dash',                 views: {                     'tab-dash': {                         templateUrl: 'templates/tab-dash.html',                         controller: 'DashCtrl'                     }                 }             })              .state('subscription', {                 url: '/subscription',                 templateUrl: 'templates/subscription.html',                 controller: 'SubscriptionCtrl'             })              .state('login', {                 url: '/login',                 templateUrl: 'templates/login.html',                 controller: 'LoginCtrl'             })              .state('test-compare', {                 url: '/test/compare',                 templateUrl: 'templates/test.html',                 controller: 'TestCompareCtrl'             })          // if none of the above states are matched, use this as the fallback         $urlRouterProvider.otherwise('/login');      });   I don't understand why the url is changing I am giving / and it test templates/test.html which is always the last state template
Your main issue here is this line:
beforeEach(module('compare'));   You are loading your entire app here instead of just the apiClient. Essentially, you are doing a full blown integration test, instead of a unit test.
You should be loading only api.client.
beforeEach(module('api.client'));   Something useful to note, you could also do something like:
$httpBackend.whenGET(/templates\/(.*)/).respond(''); which basically ignores all templates that get loaded by routers, controllers, or directives. If you do this though, it still wouldn't be considered a unit test, because you are not strictly testing just your APIClient.
Another useful note:
Anything you execute inside of .run or .config should not be an annonymous function, that way you could mock it. 
An example of this would be doing:
.config(CompareStateLoader);  CompareStateLoader.$inject = [     '$stateProvider',      '$urlRouterProvider' ];  function CompareStateLoader(     $stateProvider,      $urlRouterProvider ){     //configure states here  }   Doing this would allow you to mock CompareStateLoader and load this in your test runner.
For more information on this, please see John Papa's Angular Style Guide here.
I would suggest to compile all your templates into JS file (for example with grunt "html2js" task or karma preprocessor "ng-html2js") and do not have headache with GETing templates.
Or you also could use passThrough
$httpBackend.when('GET', /\.html$/).passThrough()   Example - http://plnkr.co/edit/pbjcDl?p=preview
But I would suggest to use first option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With