Serginho
Serginho

Reputation: 7490

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?

Upvotes: 1

Views: 476

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209042

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

Upvotes: 1

Related Questions