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

I upgraded from RC4 to the final version (2.1.0), and I am reorganizing my unit tests to match 2.1.0 syntax. This is easy except for HTTP mocking.

I cannot find examples for mocking HTTP requests in 2.1.0

Here is the RC4 HTTP unit test. How do I rewrite this in the final version 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 HELP TO 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); }); }))); 

NOTE. DO NOT PROVIDE RC code, please. Thanks

+4
source share
2 answers

First of all you need to configure TestBed . There are more TestComponentBuilder . With TestBed this is like setting up @NgModule from scratch, just for a test environment. This means that you add the component under test in declarations , add all the providers to the provider and import everything into imports .

To set up a background backend for an Http provider, you simply create Http from 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 ] } ] }) }) 

This should be for configuration, assuming you don't need any other vendors or imports that I don't know about.

For the test, you first need to do the async test, since you will perform asynchronous operations in the test. This has not changed with RC, you are just using async . If the component uses templateUrl (and you do not use Webpack), you will need to call TestBed.compileComponents() , otherwise there is no need. After that, you can create the component using 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) => { }))) 

Almost everything related to testing can be imported from @angular/core/testing . Your use of MockBackend will still be the same.

Another note: you do not need to call component.ngOnInit . This is called a wireframe when you call fixture.detectChanges()

See also:

+4
source

Many thanks to @peeskillet for helping me achieve my answer.

 import {APP_BASE_HREF} from '@angular/common'; import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {AppModule} from '../../../app.module'; import {persons} from '../../../data/persons'; import {Route1ListComponent} from './route1-list.component'; // HTTP mocking imports import {BaseRequestOptions, Http, Response, ResponseOptions} from '@angular/http'; import {MockBackend, MockConnection} from '@angular/http/testing'; describe('route1-list.component.ts', () => { let fix: ComponentFixture<Route1ListComponent>; let instance: Route1ListComponent; let injector: any; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [AppModule], providers: [{provide: APP_BASE_HREF, useValue: '/'}, MockBackend, BaseRequestOptions, { provide: Http, useFactory: (pBackend: MockBackend, pOptions: BaseRequestOptions) => { return new Http(pBackend, pOptions); }, deps: [MockBackend, BaseRequestOptions] }] }).compileComponents() .then(() => { fix = TestBed.createComponent(Route1ListComponent); instance = fix.componentInstance; injector = fix.debugElement.injector; }); })); it('should instantiate component', () => { expect(instance).toEqual(jasmine.any(Route1ListComponent)); }); it('should have expected text', () => { let el = fix.debugElement.query(By.css('section.route1-list')).nativeElement; expect(el.textContent).toMatch(/route 1 list view/i, 'should have expected text'); }); it('ngOnInit()', async(() => { let backend = injector.get(MockBackend); backend.connections.subscribe( (connection: MockConnection) => { connection.mockRespond(new Response( new ResponseOptions({ body: persons } ))); }); fix.detectChanges(); // Calls instance.ngOnInit() expect(instance.persons.length).toBe(3); })); it('ngOnInit() failure', async(() => { let backend = injector.get(MockBackend); backend.connections.subscribe( (connection: MockConnection) => { connection.mockError(new Error('error')); }); fix.detectChanges(); // Calls instance.ngOnInit() expect(instance.persons).toBeUndefined(); })); }); 

Please note that at the time of writing the Angular2 docs at ..

https://angular.io/docs/ts/latest/api/http/testing/index/MockBackend-class.html

https://angular.io/docs/ts/latest/api/http/testing/index/MockConnection-class.html

seems wrong.

When I use Injector.resolveAndCreate as described in the docs, I get an error:

The resolveAndCreate property does not exist for the typeof type injector.

To fix this, I had to base my answer on the answer provided by @peeskillet

+2
source

All Articles