Reputation: 927
Been trying to wrap my head around this angular-mocks jasmine testing for a couple of days now.. Got some basic stuff working but when wanting to spy and assert stuff on mocks i get stuck.
TEST CODE
describe("My service tests: calls correct urls and resolves", function () {
var $myService, $httpBackend, $q, deffered;
beforeEach(module('myModule', function ($provide) {
var mockEndpointService = {
getApiEndpoint: function () {
return 'mockEndPoint';
}
};
$provide.value('$endpointService', mockEndpointService);
}));
beforeEach(inject(function (_$myService_) {
$myService= _myService_;
}));
beforeEach(inject(function ($injector) {
$httpBackend = $injector.get('$httpBackend');
$q = $injector.get('$q');
deffered = $q.defer();
spyOn($q, 'defer').andReturn(deffered);
spyOn(deffered, 'resolve');
$httpBackend.when('GET', 'mockEndPoint/testtest').respond(123);
}));
it("Get calls correct URL and resolves deffered on success", function () {
$myService.get('testtest');
$httpBackend.expect('GET', 'mockEndPoint/testtest');
$httpBackend.flush(); //Added this
expect(deffered.resolve).toHaveBeenCalledWith(123); //This assert fails
});
});
SERVICE CODE
myModule.factory('$myModule', ['$http', '$q', '$endpointService', function ($http, $q, $endpointService) {
var apiPath = $endpointService.getApiEndpoint('MyApi');
this.get = function (id) {
var deferred = $q.defer();
var url = apiPath + '/' + id;
console.log('GET: ' + url);
$http.get(url).success(function (data) {
deferred.resolve(data);
}).error(function () {
deferred.reject('error: could not load thingy with id: ' + id);
});
return deferred.promise;
};
}]);
So question one, i have 3 beforeEach blocks, can i merge some of them? I get all kinds of faults when i try to do it.
Also, how would i go about to assert that the resolved is called on success of the get? You see what I have tried with above, but it does not work.
Thx in advance.
Edit: Adding the flush seems to make some difference but not the expected result, so any help regarding promises and defer is really appreciated.
Edit2: Changed title to actually reflect what i had problems with.
//TWD
Upvotes: 3
Views: 1926
Reputation: 8986
Remove $httpBackend.when
from the last beforeEach
block, and the test should look like the following:
it("Get calls correct URL and resolves deffered on success", function () {
$httpBackend.expect('GET', 'mockEndPoint/testtest').respond(123);
$myService.get('testtest');
$httpBackend.flush();
expect(deffered.resolve).toHaveBeenCalledWith(123);
});
$httpBackend.flush
must be called to resolve the promise of $http.get
. Only after that, your deferred
object's resolve would be called.
Update:
I think it's a bad idea to spy on a vendor function to begin with, it's the last thing you want to do when you're unit testing your code. And, in your service code, it's not necessary to create a new deferred object, since $http.get
will return a promise to you, so you can simplify the code like the following:
this.get = function (id) {
var url = apiPath + '/' + id;
console.log('GET: ' + url);
return $http.get(url).success(function (data) {
return data;
}).error(function () {
return 'error: could not load thingy with id: ' + id;
});
};
Now, you can test it like this:
it("Get calls correct URL and resolves deffered on success", function () {
$httpBackend.expect('GET', 'mockEndPoint/testtest').respond(123);
$myService.get('testtest').then(function(data) {
expect(data).toEqual(123);
});
$httpBackend.flush();
});
Upvotes: 4