Injected $stateParams and $state into jasmine angular js test getting undefined

20,741

Solution 1

I think you might be misunderstanding how the router is working with the controller. When you're unit testing a controller, you're not executing a route or entering a ui-router state. Those states and routes are what trigger controllers to be executed when the application is running normally. But in a unit test, you're executing the controller explicitly using $controller. So you're skipping the routing part altogether. Which means you need to mock the object that the ui-router would normally create for you, $stateparams.

describe('Detail Ctrl', function() {

  var scope, ctrl, httpBackend, stateparams, listingId; 

  beforeEach(angular.mock.module("backpageApp"));
  //don't need to inject state or stateparams here
  beforeEach(angular.mock.inject(function($controller, $rootScope, _$httpBackend_) {
    httpBackend = _$httpBackend_;
    stateparams = { listingId: 1 }; //mock your stateparams object with your id

    //you should be expecting the get request url from the controller, not the route
    httpBackend.expectGET('data/' + stateparams.listingId + '.json').respond([{id: 1 }, {id: 2}, {id:3}, {id:4}, {id:5}, {id:6}, {id:7}, {id:8}, {id:9}, {id:10}]);
    scope = $rootScope.$new(); 
    //pass your mock stateparams object to the controller 
    ctrl = $controller("DetailCtrl", {$scope:scope, $stateParams:stateparams}); 
  }));

   it('the images for each listing should exist', function() {
    httpBackend.flush(); 
    //I don't see images set in your controller, but you 
    //could check scope.extrainfo here
    expect(scope.images).toBe(true)
  });
});

Solution 2

Adding the stateMock.js and then including the module

beforeEach(function() {
    module('stateMock');
    module('mean');
    module('mean.system');
    module('mean.companies');
  });

code here for stackMock.js: github code for stateMock

Reference: UI-router interfers with $httpbackend unit test, angular js.

Share:
20,741
Jngai1297
Author by

Jngai1297

Updated on July 09, 2022

Comments

  • Jngai1297
    Jngai1297 almost 2 years

    I am writing a jasmine test for my DetailCtrl. I have 10 json file each with file names like this

    1.json
    2.json
    3.json
    

    in my data folder

    Here is my Detail Ctrl

    backpagecontrollers.controller('DetailCtrl', function($scope, $stateParams, $http) {
      $http.get('data/' +  $stateParams.listingId + '.json').success(function(data) {
          $scope.extrainfo = data; 
      });
    }); 
    

    The detail controller is fetching each 1.json, 2.json, 3.json file from my data folder.

    Here is a part of my route

    .state('listingdetail', {
          url: "/listings/:listingId",
          templateUrl: "partials/detail.html",
          controller: 'DetailCtrl'
        })
    

    Lets head back to the test, I injected both the $stateParams and the $state into the test.

    I want to test that for each json file above the images exist inside my json file. I am setting the httpbackend to get the local host url plus the listingId from the $stateparams which I configured as part of the routes but the listingId is coming back as undefined. Am I suppose to inject something else into my test?

    describe('Detail Ctrl', function() {
    
          var scope, ctrl, httpBackend, stateparams, listingId; 
    
          beforeEach(angular.mock.module("backpageApp"));
          beforeEach(angular.mock.inject(function($controller, $rootScope, _$httpBackend_,    $stateParams, $state) {
            httpBackend = _$httpBackend_;
            stateparams = $stateParams; 
            listingId = stateparams.listingId;
    
            httpBackend.expectGET('http://localhost:8000/#/listings/' + listingId).respond([{id: 1 }, {id: 2}, {id:3}, {id:4}, {id:5}, {id:6}, {id:7}, {id:8}, {id:9}, {id:10}]);
            scope = $rootScope.$new(); 
            ctrl = $controller("DetailCtrl", {$scope:scope}); 
          }));
    
           it('the images for each listing should exist', function() {
            httpBackend.flush(); 
            expect(scope.images).toBe(true)
          });
        });
    

    I am getting this error

    Error: Unexpected request: GET data/undefined.json
        Expected GET http://localhost:8000/#/listings/undefined
    
  • Jngai1297
    Jngai1297 over 10 years
    Can you point me to some tutorials online that explain this more? the docs/blogs aren't so good on google.
  • JeffB
    JeffB over 10 years
    This one's pretty good, I think: nathanleclaire.com/blog/2013/12/13/…
  • Michael J. Calkins
    Michael J. Calkins about 10 years
    Gah I'm always overthinking it when it's just that simple.