Reputation: 1985
I have a Jasmine test for one of my Angular services which fetches data from a server and makes it publicly accessible. The server returns JSON, just an array of objects [{...}, {...}, ...]
.
Now I tried writing a test with a mocked out http backend:
var mockLibrary = [{}, {}];
beforeEach(inject(function(LibrarySvc) {
libSvc = LibrarySvc;
}));
it('should fetch the library', function(done) {
inject(function($httpBackend) {
$httpBackend.expectGET('/library').respond(200, mockLibrary);
libSvc.getLibrary()
.then(function(response) {
expect(_.isEqual(response, mockLibrary)).toBeTruthy();
})
.finally(done);
$httpBackend.flush();
});
});
The code in my service is as follows:
var library;
var deferred = $q.defer();
$http.get('/library')
.then(function(data) {
library = data;
deferred.resolve(library);
}, function(err) {
deferred.reject(err);
});
So, the service assigns the JSON response body of the server to an internal library
variable and resolves the promise with it. Now when running this test, it fails, because response
in the test is not equal to mockLibrary
. Instead, response
is this:
Object{data: [Object{}, Object{}], status: 200, headers: function (c){ ... }, config: Object{method: 'GET', transformRequest: [...], transformResponse: [...], url: '/library', headers: Object{Accept: ...}}, statusText: ''}
and what I actually wanted would now be response.data
in the test, and data.data
in my service logic.
Why does Angular do this? Is this implicitly suggesting that JSON responses from my server should always be a hash that holds the actual response data in a data
attribute? Why would I ever want to adjust my service logic to an Angular test? Or did I miss something? The docs for $httpBackend weren't helpful on this matter.
Further notes: I'm using underscore.js for a deep equals check at _.isEqual(...)
, and Jasmine 2.0 to test asynchronously (thus the function(done)
syntax).
Upvotes: 0
Views: 181
Reputation: 11547
When using .then()
for the $http
, the first parameter won't be the data from your server.
It will be a wrapper object like you see and the data from your server will be in .data
.
There is no different between your service and the test. You might be confused and think that the data
parameter in your service is the data from your server, it isn't.
Therefore, yes, you have to use response.data
in your test and data.data
in your service. But I suggest you rename the data
parameter in your service to response
for consistency.
Also see: $http documentation
Upvotes: 1