I am writing the beginning of an Angular service that will consume an API, and I started with stubbing out all the request actions. Nothing actually happens with this service yet; it's basically a wrapper for $http
. I'm running into an interesting problem with the tests for this: I have mocked out a PUT
request that doesn't seem to work as I expect it to, and I'm wondering where my understanding has failed.
Essentially, when I check for observation.get(1)
, the request is mocked correctly and the test passes. But if I do observation.update({'some_key': 'some_value'})
, I get this error:
Chrome 51.0.2704 (Mac OS X 10.11.5) Observation responds to #save FAILED
Error: No response defined !
I think I have defined a response in the beforeEach() function body, yet the spec still fails. It seems strange that every other test for this passes using the exact same syntax. What am I doing wrong?
class Observation {
constructor($http, AppSettings) {
'ngInject';
Object.assign(this, {$http, AppSettings});
this.headers = {
'Authorization': 'Token token=myfancytoken'
};
this.endpoint = `${this.AppSettings.API_URL}/api/${this.AppSettings.API_VERSION}/observations`;
}
get(id) {
this.id = id;
let params = {
url: `${this.endpoint}/${this.id}.json`,
method: 'GET'
};
return this.request(params);
}
save(data) {
if (typeof this.id === 'undefined') {
throw {message: 'Cannot save object without an id'};
}
let params = {
url: `${this.endpoint}/${this.id}.json`,
method: 'PUT',
data: data
};
return this.request(params);
}
request(params) {
Object.assign(params, {headers: this.headers});
return this.$http(params)
.then((response) => { return response.data; })
.catch((response) => { return response.status; });
}
/*
* Other actions omitted for brevity
*/
}
export default Observation;
import Observation from './observation';
describe('Observation', () => {
let $httpBackend, AppSettings, observation, $http, obj, successResponse;
beforeEach(() => {
AppSettings = {
"API_URL": 'http://localhost:3000',
'API_VERSION': 'v1'
};
inject(($injector) => {
$httpBackend = $injector.get('$httpBackend');
$http = $injector.get('$http');
});
observation = new Observation($http, AppSettings);
successResponse = (response) => {
obj = response.data;
};
/* Mock the backend */
// GET #show
$httpBackend
.when('GET', `${observation.endpoint}/1.json`)
.respond(200, {data: {}});
// PUT #save
// FIXME: Not working for some reason and needs to be defined in the test itself?
$httpBackend
.when('PUT', `${observation.endpoint}/${observation.id}.json`)
.respond(200, {data: {'id': 1}});
});
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('responds to #get', () => {
observation
.get(1)
.then(successResponse);
$httpBackend.expect('GET', `${observation.endpoint}/1.json`)
$httpBackend.flush();
expect(obj).toEqual({});
});
/* Other test cases omitted for brevity */
it('responds to #save', () => {
observation.id = 1;
observation
.save({'first_name': 'Lisa'})
.then(successResponse);
// FIXME: Why doesn't this work?
$httpBackend
.expect('PUT', `${observation.endpoint}/${observation.id}.json`);
// .respond(200, {data: {'id': 1}});
$httpBackend.flush();
expect(obj.id).toBe(1);
});
it('throws an error if #save is called without an id on the object', () => {
expect(() => {observation.save()}).toThrowError(Error, 'Cannot save object without an id');
});
});
$httpBackend
.when('PUT', `${observation.endpoint}/${observation.id}.json`)
At this point observation
has no id.