I'm trying to write a unit test for a controller which fetches article details using $http service.
Controller:
.controller('ArticleDetailCtrl',function($scope, Article, $routeParams, API_URL, ARTICLE_URL, $http, $sce){
$scope.url = API_URL + ARTICLE_URL + '/' + $routeParams.articleId;
$http.get($scope.url).then(function(response) {
//console.log(response.data);
$scope.heading = response.data.Headline;
$scope.rawBody = response.data.Body;
$scope.body = $sce.trustAsHtml($scope.rawBody);
$scope.image = response.data.Assets[0].URL;
});
});
Unit test:
'use strict';
describe('Controller: Article', function () {
var scope,
$httpBackend,
articleEndpoint;
// load the controller's module
beforeEach(module('myApp'));
describe('ArticleDetailCtrl', function () {
var ArticleDetailCtrl,
jsonObject,
ArticleId = '123';
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, _$httpBackend_, Article, API_URL, ARTICLE_URL) {
scope = $rootScope.$new();
ArticleDetailCtrl = $controller('ArticleDetailCtrl', { $scope: scope });
$httpBackend = _$httpBackend_;
articleEndpoint = API_URL + ARTICLE_URL + '/' + ArticleId;
jsonObject = {
'Headline': 'Headline',
'Body': '<p>Body</p>',
'Assets': [
{
'URL': 'path/to/image/article1.jpg'
}
]
};
$httpBackend.when('GET', articleEndpoint).respond(jsonObject);
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should fetch article details from the API', function () {
//expect(scope.articles.length).toEqual(3);
$httpBackend.expectGET(articleEndpoint);
$httpBackend.flush();
});
});
});
But I keep on getting the following error:
Error: Unexpected request: GET http://localhost:3000/api/articles/undefined
Expected GET http://localhost:3000/api/articles/123
at $httpBackend (/Users/gill/Documents/projects/angularjs-test/app/bower_components/angular-mocks/angular-mocks.js:1179)
at sendReq (/Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:8181)
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:7921
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:11319
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:11405
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:12412
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular/angular.js:12224
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular-mocks/angular-mocks.js:1438
at /Users/gill/Documents/projects/angularjs-test/test/spec/controllers/article.js:77
Error: Unsatisfied requests: GET http://localhost:3000/api/articles/123
at /Users/gill/Documents/projects/angularjs-test/app/bower_components/angular-mocks/angular-mocks.js:1472
at /Users/gill/Documents/projects/angularjs-test/test/spec/controllers/article.js:65
This is the first time am writing unit tests which I followed along by reading some tutorials. I don't know what am I doing wrong?
Your problem is a simple, but a common one.
When you write your Jasmine / Karma unit tests, creating your controllers are almost automatic using the $controller service. That means, for the most part, you can say from your unit test
And AngularJS will figure out its dependent services, inject them and create an instance of the controller for you to unit test.
There is one exception to this:
I notice in your unit test you create the controller as
ArticleDetailCtrl = $controller('ArticleDetailCtrl', { $scope: scope });
So at this point, you tell AngularJS what object to use when the controller asks for $scope as a dependent service. But in your controller, you also inject $routeParams. And based on its articleId you create the URL for the request.
So if you change your controller instantiation code to:
That should now create the correct URL (instead of using undefined for articleId, which was the error)
Let me know if that helps.