问题
I'm new to angular unit testing. What I want to do is getting actual results from my API. I checked this documentation but as I understand, I should create mock responses. Here is my code,
myService.ts:
...
public GetAll = (apiname: string): Observable<Object> => {
return this._http.get("foo/" + apiname,{headers:this.options}); //this.options = newHttpHeaders({'ContentType':'application/json','Accept':'application/json'});
}
...
myService.spec.ts:
...
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientModule,
HttpClientTestingModule
],
providers: [
MyService
]
});
});
afterEach(inject([HttpTestingController], (backend: HttpTestingController) => {
backend.verify();
}));
it('GetAll() should work', () => {
const testData = {id: "123"};
service.GetAll("items").subscribe(data => {
//console.log(JSON.stringify(data));
});
const req = httpTestingController.expectOne('foo/items');
expect(req.request.method).toEqual('GET');
req.flush(testData);
httpTestingController.verify();
});
When I write the result in console, it writes 'testData' instead of 'data'. As I said before, I want to get actual result from my API, not mock result. Sorry if it is a silly question but how can I do that ? Thanks for advice.
回答1:
Here is a working solution to get a real data
auth.service.te
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private http: HttpClient) {}
getPost(postId: number): Observable<Post> {
return this.http.get<Post>(
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
}
}
auth.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
import { HttpClientModule } from '@angular/common/http';
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule],
});
service = TestBed.inject(AuthService);
});
it('should get the data successfully', (done: DoneFn) => {
service.getPost(1).subscribe((post: Post) => {
console.log('data is ', post);
expect(post.id).toEqual(1);
done();
});
});
});
Hope is helps
回答2:
If you are not mocking the service call, you can actually wait for the response. Since this is an async call, you will have to let the test runner framework know that you are waiting for the result. You can do that with providing a done function
.
Sample code:
it('GetAll() should work', (done) => {
service.GetAll("items").subscribe(data => {
expect(data).toContain("something");
//expect ...
done(); // <= done fn invoked. This marks end of test case.
});
});
More info: https://codecraft.tv/courses/angular/unit-testing/asynchronous/#_jasmines_code_done_code_function
回答3:
notice that flush resolves the request , then you can use
service.GetAll(data).subscribe((response : HttpResponse<any>) => {
expect(response.status).toBe(200);
expect(response.body).toEqual(testData);
});
const req = httpTestingController.expectOne('foo/items');
expect(req.request.method).toEqual('GET');
req.flush(new HttpResponse({ status: 200, body: testData }));
来源:https://stackoverflow.com/questions/49550041/angular-testing-getting-actual-http-response