Injected $stateParams and $state into jasmine angular js test getting undefined
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.
Jngai1297
Updated on July 09, 2022Comments
-
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 thelistingId
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 over 10 yearsCan you point me to some tutorials online that explain this more? the docs/blogs aren't so good on google.
-
JeffB over 10 yearsThis one's pretty good, I think: nathanleclaire.com/blog/2013/12/13/…
-
Michael J. Calkins about 10 yearsGah I'm always overthinking it when it's just that simple.