user9195230
user9195230

Reputation:

How to testing a service in Angular 7

I want to test the data I receive from my service. I read angular documentation and I followed observable example but I don't receive any data when I subscribed to the observable. Console.log() isn't working inside the subscribe.

The service is working properly and get the right data in a real environment.

I tried to use async and doneFn but they didn't work both of them got time out.

Service File

export class BackService {

  URL = '********'; // I removed url for security.

  constructor(private httpClient: HttpClient) { }

  getAllForms(): Observable<Array<object>> {
    return this.httpClient.get<Array<object>>(`${this.URL}/allForms`);
  }

  getFormById(formId): Observable<Array<object>> {
    return this.httpClient.get<Array<object>>(`${this.URL}/form/${formId}`);
  }
}

Test Service File

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { BackService } from './back.service';


describe('BackService', () => {
  let httpMock: HttpTestingController;
  let backService: BackService;
  beforeEach(() => {
    TestBed.configureTestingModule({
    imports: [ HttpClientTestingModule ],
    providers: [BackService]
    });
    backService = TestBed.get(BackService);
    httpMock = TestBed.get(HttpTestingController);
  });
  it('should be created', () => {
    expect(backService).toBeTruthy();
  });
  describe('Methods', () => {
    describe('All Forms', () => {
      it('should use GET method', () => {
        backService.getAllForms().subscribe();
        const req = httpMock.expectOne(`${backService.URL}/allForms`);
        expect(req.request.method).toBe('GET');
      });
      it('should use the right url', () => {
        backService.getAllForms().subscribe();
        const req = httpMock.expectOne(`${backService.URL}/allForms`);
        expect(req.request.url).toBe(`${backService.URL}/allForms`);
      });
      it('should return the right data', () => {
        const mockData = [{'_id': 435345345, '_type': 'window'}]
        backService.getAllForms().subscribe(data => {
          expect(data).toEqual(mockData);
        });
      });
    });
  });

Upvotes: 1

Views: 2605

Answers (3)

Iulian Cucoanis
Iulian Cucoanis

Reputation: 205

Can you try with MockBackend instead?

import { TestBed, inject } from "@angular/core/testing";
import {
  HttpModule,
  Http,
  Response,
  ResponseOptions,
  XHRBackend
} from "@angular/http";
import { MockBackend } from "@angular/http/testing";
import { BackService } from "./back.service";

describe("BackService", () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpModule],
      providers: [BackService, { provide: XHRBackend, useClass: MockBackend }]
    });
  });
  describe("getAllForms()", () => {
    it("should return an Observable<Array<Form>>", inject(
      [BackService, XHRBackend],
      (backService, mockBackend) => {
        const mockResponse = {
          data: [
            { id: 0, form: "Form 0" },
            { id: 1, form: "Form 1" },
            { id: 2, form: "Form 2" },
            { id: 3, form: "Form 3" }
          ]
        };

        mockBackend.connections.subscribe(connection => {
          connection.mockRespond(
            new Response(
              new ResponseOptions({
                body: JSON.stringify(mockResponse)
              })
            )
          );
        });

        backService.getAllForms().subscribe(forms => {
          expect(forms.length).toBe(4);
          expect(forms[0].form).toEqual("Form 0");
          expect(forms[1].form).toEqual("Form 1");
          expect(forms[2].form).toEqual("Form 2");
          expect(forms[3].form).toEqual("Form 3");
        });
      }
    ));
  });
});

Upvotes: 0

AndriusDGT
AndriusDGT

Reputation: 16

First 2 tests look ok, for third test to receive data that you can test on, you have to trigger that "httpMock" by calling its flush() method with necessary object you want your httpClient to return.

This should work for third test:

it('should return the right data', () => {
    const mockData = [{'_id': 435345345, '_type': 'window'}]
    backService.getAllForms().subscribe(data => {
      expect(data).toEqual(mockData);
    });
    const req = httpMock.expectOne(`${backService.URL}/allForms`);
    req.flush(mockData);
});

Upvotes: 0

Eric
Eric

Reputation: 43

we do pact tests because you have to mock a lot which didn't feel real for us.

Example

 import {PactWeb} from '@pact-foundation/pact-web';

    describe('FooService', () => {
    let provider: PactWeb;

      beforeAll(async () => {
        await provider.addInteraction({
                    state: 'I have an foo',
                    uponReceiving: 'a request to create an bar',
                    withRequest: {
                      method: 'POST',
                      path: '/url/bars',
                      body: {
                        foo: '123456',
                        bar: 'abcd'
                      }
                    },
                    willRespondWith: {
                      status: 200,
                      headers: {'Content-Type': 'application/json'},
                      body: {
                        foo: '123456',
                        bar: 'abcd'
                      }
                    }
                  });
               });

            it('should create one bar and respond with that bar', async () => {
              const service: FooService = TestBed.get(FooService);
              (service as any).apiBasePath = provider.mockService.baseUrl + 'url';
              const result = await service.createBar({
                        foo: '123456',
                        bar: 'abcd'
              }).toPromise();

              expect(result.id).toEqual('some-random-uuid');

            });

    afterAll(function (done) {
      provider.finalize()
        .then(function () {
          done();
        }, function (err) {
          done.fail(err);
        });
    });
        });

I assume, that you have a service called "createBar" that you want to test.

State Is just to know what you are doing, so it is the state of the provider. He has a foo. And uponReceiving of the request he should create a bar

withRequest Shows how the request should look like

willRespondWith Shows the response.

Upvotes: 0

Related Questions