*Update - see end of post*
I have a controller that depends on a service. the service encapsulates $resource. Here is the code
app.controller('charactersController', function ($scope, $routeParams, $location, marvelRepository) {
var page = parseInt($routeParams.pageNumber);
marvelRepository.fetch(page - 1).then(function (data) {
$scope.characters = data.results;
$scope.paging = {
page: page,
total: data.total,
pageSize: data.limit
};
});
$scope.goto = function (pageNumber) {
$location.path('/characters/' + pageNumber);
};
});
marvel.service('marvelRepository', function (hash, $resource) {
var extended = ng.extend(hash.authenticate(), { id: '@id' });
var characters = $resource('http://gateway.marvel.com/v1/public/characters/:id', extended);
return {
get: function (characterId) {
return characters
.get({ id: characterId })
.$promise
.then(function (response) {
if (response.code !== 200) {
throw response;
}
return response.data.results[0];
});
},
fetch: function (pageIndex) {
return characters
.get({ limit: 20, offset: pageIndex * 20 })
.$promise
.then(function (response) {
if (response.code !== 200) {
throw response;
}
return response.data;
});
}
};
});
the hash dependency creates authentication parameters for the marvel api: public key, timestamp & hash value.
The website work and I can display a list of characters. Now I'm trying to write tests (because angular promotes easy testablity....)
Here is my test
describe("Angular Demo - Test", function () {
beforeEach(angular.mock.module('demo'));
describe('requiring Marvel respository', function() {
var url = 'http://gateway.marvel.com/v1/public/characters?apikey=123&hash=abc123&limit=20&offset=0&ts=20140601073322';
var httpBackend, location, scope, controller;
beforeEach(module(function (hashProvider) {
hashProvider.override({
apikey: '123',
ts: '20140601073322',
hash: 'abc123'
});
}));
beforeEach(inject(function ($httpBackend, $location, $rootScope, $controller) {
controller = $controller;
location = $location;
scope = $rootScope.$new();
httpBackend = $httpBackend;
}));
afterEach(function () {
//httpBackend.verifyNoOutstandingExpectation();
//httpBackend.verifyNoOutstandingRequest();
});
describe('charactersController', function () {
var characters;
beforeEach(function() {
characters = new Array(20);
httpBackend.when('get', url).respond({ data: { results: characters, offset: 2, limit: 20, total: 100 } });
});
it('should be able to get a page of characters', function () {
httpBackend.expect('get', url);
controller('charactersController', { $scope: scope, $routeParams: { pageNumber: 1 } });
httpBackend.flush();
expect(scope.characters).toBe(characters);
});
it('should be able to configure paging', function () {
httpBackend.expect('get', url);
controller('charactersController', { $scope: scope, $routeParams: { pageNumber: 1 } });
httpBackend.flush();
expect(scope.paging.total).toBe(100);
expect(scope.paging.page).toBe(1);
expect(scope.paging.pageSize).toBe(20);
});
it('should be able to navigate to another page of characters', function () {
controller('charactersController', { $scope: scope });
scope.goto(5);
expect(location.path()).toBe('/characters/5');
});
});
});
});
when I execute the tests I get the following results
Error: Unexpected request: GET http://gateway.marvel.com/v1/public/characters/1?apikey=123&hash=abc123&ts=20140601073322
Expected get http://gateway.marvel.com/v1/public/characters/1?apikey=123&hash=abc123&ts=20140601073322
Error: Unexpected request: GET http://gateway.marvel.com/v1/public/characters/1?apikey=123&hash=abc123&ts=20140601073322
Expected get http://gateway.marvel.com/v1/public/characters/1?apikey=123&hash=abc123&ts=20140601073322 at $httpBackend (/tests/angular-mock.js:1172:13) at sendReq (/js/angular/angular.js:8286:9) at $http.serverRequest (/js/angular/angular.js:8027:16) at wrappedCallback (/js/angular/angular.js:11574:81) at wrappedCallback (/js/angular/angular.js:11574:81) at /js/angular/angular.js:11660:26 at Scope.$eval (/js/angular/angular.js:12724:28) at Scope.$digest (/js/angular/angular.js:12536:31) at Function.$httpBackend.flush (/tests/angular-mock.js:1447:20) at Object. (/tests/tests.js:113:29)
if I add console statements throughout my code. i can see that marvelRepository.fetch(1) is getting called. however .$promise.then() doesn't appear to execute.
And what doesn't make sense to me is the 1st two lines of the error. First it states an unexpected request was made and then it says an expected call to the url was made. and it's the same url.
any ideas on what I'm overlooking?
*Update*
I updated the structure of the test. setting up both when and expect calls.
I also found if I change my backend calls from when('get', ... to when('GET', ... i receive the following test error
undefined: undefined
No stacktrace or line numbers, but undefined. Reviewing the original error it states
Error: Unexpected request: GET url....
Expected get url...
so I'm wondering if it's failing because of the case sensitivity comparing the request method. However, I think it's a timing issue. The service is injected and the method is called, however the promise.then(cb) doesn't execute. But maybe it's not firing because the request methods don't match so $httpbackend doesn't return?