onurcanak
onurcanak

Reputation: 109

Angular Testing Getting Actual HTTP Response

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.

Upvotes: 4

Views: 8569

Answers (3)

Omar Hasan
Omar Hasan

Reputation: 798

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();
    });
  });
});

enter image description here Hope is helps

Upvotes: 2

amir
amir

Reputation: 181

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 }));

Upvotes: 2

DDan
DDan

Reputation: 8276

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

Upvotes: 0

Related Questions