I have a service I want to unit test in angular 4 typescript jasmine.
Now, the http
is doing a post
, and it returns an identity, however.. it is not sending anything.
I want to just have good code coverage but i don't understand how to quite complete this mocking statement.
here is the method for http post in my service file
addSession() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.url, JSON.stringify({}), options)
.map((response: Response) => response.json());
}
Then the SPEC FILE , which i don't get what to really test, i suppose faking that i received a number back from the service http post, the response should be something like 000000014
Spec
import { TrackerFormService } from './tracker-form.service'
import { Observable } from 'rxjs/Observable'
describe('TrackerFormService', () => {
let trackerFormService: TrackerFormService,
mockHttp;
beforeEach(() => {
mockHttp = jasmine.createSpyObj('mockHttp', ['get', 'post', 'put']
)
trackerFormService = new TrackerFormService(mockHttp);
});
describe('addSession', () => {
it('add session ', () => {
// how to test, what to test?
// response , is a number? how to mock/fake this?
})
})
})
Well the way you did setup the test/mock you can fake the return of the post call and check that you got the result you expected. By doing so you will test that the mocked response will be properly converted by your map statement. With your spy you can also check how the post method was called. This will check if the options match what you expect.
But in my opinion that’s a rather complicated solution. I'd prefer to avoid mocks and spies by splitting the method so every method is just doing one thing. Because your addSession method is currently doing three different (yet logically dependent) things:
If you break the method up in three you can easily test method #1 and #3 in separate tests and method #2 would only contain the call to the http library. This allows you to achieve the same test value as above without calling the http library.
Now what about method #2... it's still untested and in my opinion there is no reason to test it at all. Because you did not write that code. Also if you are using angulars http module I am sure they have solid unit tests themselves.
The response of your service should already be covered by an additional integration test, run less frequently checking the service api will still return what you expect.
If you really want that one line green in your code coverage, then you could optionally use a library called nock. Nock will intercept all xhr traffic your app will cause. In your test file you can map xhr requests to mocked responses with the nock object.
copied from: https://www.npmjs.com/package/nock
For reference and additional information about testing in general and how much to test i recommend watching "Budgeting Reality" by Justin Searls
With Angular 4.3 came the HttpClient service which replaces Http and provides an easier way to mock HTTP requests. It's well documented on the official page: https://angular.io/guide/http
Sample test case for http service requests
In order to achieve what you want, the mock you need is a simple function that returns the same as the POST would do normally; another thing is your test should not hit the server for real, so you would need something like this (you might need to add other dependencies):