Search code examples
angularangular2-testing

Angular 2 RC-5 Async testing is not working


That's the code:

import {
  async,
  inject,
  TestBed
} from '@angular/core/testing';
import {
  Http,
  Response,
  ResponseOptions,
  RequestOptions,
  BaseRequestOptions,
  ConnectionBackend
} from "@angular/http";
import {MockBackend, MockConnection} from "@angular/http/testing";
import {HttpInterceptor, RequestWrapped} from "./http.interceptor.service.ts";

describe("Http interceptor", () => {
  beforeEach(() =>{
    TestBed.configureTestingModule({
      providers: [
        MockBackend,
        BaseRequestOptions,
        {provide: ConnectionBackend, useClass: MockBackend},
        {provide: RequestOptions, useClass: BaseRequestOptions},
        Http
      ],
    });
  });

  it('should get blogs', inject([Http, MockBackend], (http:Http, backend:MockBackend) => {
    let connection:MockConnection;
    backend.connections.subscribe(connection =>
      connection.mockRespond(new Response(new ResponseOptions('awesome')))
    );
    http.request('data.json').subscribe((res) => {
      expect(res.text()).toBe('awesome2');
    });
  }));
});

This test should fail, obviouly awesome is not equal awesome2, why is not working?


Solution

  • It's because the it method finishes executing before the async callback. In vanilla Jasmine you would handle asynchrony with done

    it('', function (done) {
      setTimeout(function () {
        expect(2).toBe(2);
        done();
      }, 1000);
    });
    

    The done is how Jasmine knows we're finished with all the asynchronous events and the test is complete.

    With Angular, instead of explicitly calling done, we should the fundtion in async. This will wrap the entire method in a zone, where it keeps track of all async calls. when all the async calls are done, then the test completes. This is different from a synchronous test where once the method completes, the test is complete

    import { async } from '@angular/core/testing';                
    
                        // async wapper
    it('should get blogs', async(inject([Http, MockBackend], (http:Http, backend:MockBackend) => {
      let connection:MockConnection;
      backend.connections.subscribe(connection =>
        connection.mockRespond(new Response(new ResponseOptions('awesome')))
      );
      http.request('data.json').subscribe((res) => {
        expect(res.text()).toBe('awesome2');
      });
    })));
    

    There is also fakeAsync, that allows you to control the "ticks"

    it('should get blogs', fakeAsync(inject([Http, MockBackend], (http:Http, backend:MockBackend) => {
      let connection:MockConnection;
      backend.connections.subscribe(connection =>
        connection.mockRespond(new Response(new ResponseOptions('awesome')))
      );
      let text;
      http.request('data.json').subscribe((res) => {
        text = res.text();
      });
      tick();
      expect(res.text()).toBe('awesome2');
    })));