Search code examples
unit-testingangular

How to write an HTTP mock unit test in Angular 2 final release?


I have moved from RC4 to final release (2.1.0) and I am refactoring my unit tests to conform to 2.1.0 syntax. This is easy except for HTTP mocking.

I cannot find any examples for how to mock HTTP requests in 2.1.0

Here is an RC4 HTTP unit test. How would I re-write this in final release 2.1.0?

it('ngOnInit()',
  async(inject([TestComponentBuilder, XHRBackend], (tcb:TestComponentBuilder, mockBackend:MockBackend) => {
  tcb.createAsync(Route1ListComponent).then((fix:ComponentFixture<Route1ListComponent>) => {

    // THIS BLOCK OF CODE I NEED RE-WRITE TO 2.1.0
    mockBackend.connections.subscribe(
      (connection:MockConnection) => {
        connection.mockRespond(new Response(
          new ResponseOptions({
              body: persons
            }
          )));
      });

    // THIS BLOCK OF CODE WILL NOT CHANGE
    let instance = fix.componentInstance;
    instance.ngOnInit();
    expect(instance.persons.length).toBe(3);
  });
})));

Unfortunately, I cannot use RC code.


Solution

  • First thing you need to do is configure the TestBed. There's no more TestComponentBuilder. With the TestBed, it's like configuring an @NgModule from scratch, just for the test environment. This means you will add the component under test to the declarations, add any providers to the provider, and any imports to the imports.

    To configure the mock backend for Http provider, you would just create the Http from the MockBackend.

    beforeEach(() => {
      TestBed.configureTestingModule({
        imports: [ HttpModule ],
        declarations: [ RouteListComponent ],
        providers: [
          MockBackend,
          BaseRequestOptions,
          {
            provide: Http,
            useFactory: (backend: MockBackend, options: BaseRequestOptions) => {
              return new Http(backend, options);
            },
            deps: [ MockBackend, BaseRequestOptions ]
          }
        ]
      })
    })
    

    That should be it for the configuration, assuming you don't need any other providers or imports I don't know about.

    For the test you'll first want to make it an async test, as you'll be doing asynchronous operations in the test. This hasn't changed from RC, you just use async. If the component uses templateUrl (and you're not using Webpack), then you will need to call TestBed.compileComponents(), otherwise no need to. After that you can create the component with TestBed.createComponent

    let fixture: ComponentFixture<RouteListComponent>;
    let component: RouteListComponent;
    
    beforeEach(async(() => {
      TestBed.configureTestingModule({ ... })
      .compileComponents().then(() => {
        fixture = TestBed.createComponent(RouteListComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    }));
    
    it('...', async(inject([MockBackend], (backend: MockBackend) => {
    
    })))
    

    Pretty much all the things above related to testing can be imported from @angular/core/testing. Your use of the MockBackend would still be the same.

    Another note, you don't need to call the component.ngOnInit. That is called by the framework when you call fixture.detectChanges()

    See Also: