angular: unable to mock http response, when invoked from service constructor

[ x ] bug report => search github for a similar issue or PR before submitting

Got following code:

@Injectable()
export class AttributeTypesService {

  constructor(private http: Http) {
    this.getItems();
  }

  public getItems() {
console.log("get items");
    this.http.get(SOME_ENDPOINT).subscribe(value=>{
      console.log("GOT HTTP RESPONSE");
      console.log(value);
    });
  }
}

and following test:

describe("Products service", () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [

        BaseRequestOptions,
        MockBackend,
        HttpModule,

        provide(Http, {
          useFactory: (mockBackend: ConnectionBackend,
                       defaultOptions: BaseRequestOptions) => {
            return new Http(mockBackend, defaultOptions);
          }, deps: [MockBackend, BaseRequestOptions]}),

        AttributeTypesService,
      ],
    });
  });

  describe("some suite", () => {
    it("some test", inject([AttributeTypesService, MockBackend], fakeAsync((service, mockBackend) => {
      mockBackend.connections.subscribe(c => {
        console.log("BACKEND HIT");
        let response: ResponseOptions;
        c.mockRespond(new Response(new ResponseOptions({status: 200, body: "blablablabla"})));
      });

      service.getItems();
      console.log("test");
    })));
  });
});

Current behavior Output from my test is:

LOG: 'get items'
LOG: 'get items'
LOG: 'BACKEND HIT'
LOG: 'GOT HTTP RESPONSE'
LOG: Response{_body: 'blablablabla', status: 200, ok: true, statusText: null, headers: null, type: null, url: null}
LOG: 'test'

Expected behavior I am expecting following output:

LOG: 'get items'
LOG: 'BACKEND HIT'
LOG: 'GOT HTTP RESPONSE'
LOG: Response{_body: 'blablablabla', status: 200, ok: true, statusText: null, headers: null, type: null, url: null}
LOG: 'get items'
LOG: 'BACKEND HIT'
LOG: 'GOT HTTP RESPONSE'
LOG: Response{_body: 'blablablabla', status: 200, ok: true, statusText: null, headers: null, type: null, url: null}
LOG: 'test'

As you can see getItems() method is invoked twice - one from test, and one from constructor - and it is logging get items twice. Unfornatelly it is touching mockBackend only once (when it is called directly from test).

  • Angular version: 2.0.0-rc.5
  • Browser: [all ]
  • Language: [TypeScript 1.8 ]

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (2 by maintainers)

Most upvoted comments

Using a factory wrapped in a fakeAsync callback to provide the service solved a problem like this for me:

describe("Testing MyService with asyncronous call in constructor", () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        YOUR_PROVIDERS,
        {
          provide: MyService,
          useFactory: fakeAsync((http) => {
            return new MyService(http);
          }),
          deps: [Http]
        }
      ],
    });
  });

  it('should init', inject([MyService], (myService) => {
    // asyncronous callback in constructor is solved
    expect(myService).toBeDefined();
  }));
});