2

I have been slightly diverging from the guidance in Testing Services in Angular 2 to test this method, loadIndex():

loadIndex(): Promise<Response> {
    this.index = null;
    this.isLoaded = false;
    this.isLoading = true;

    const promise = this.client
        .get('./src/assets/data/index.json') // TODO: inject this from config?
        .toPromise();
    promise
        .catch(() => {
            this.isError = true;
            this.isLoaded = false;
        })
        .then(responseOrVoid => {
            const response = <Response>responseOrVoid;
            if (!response) {
                return;
            }

            this.index = response.json().data as Array<BlogEntry>;
            if (!this.index) {
                return;
            }

            this.isLoaded = true;
            this.isLoading = false;
        });

    return promise;
}

with this test:

import { TestBed, async, getTestBed } from '@angular/core/testing';
import {
    BaseRequestOptions,
    Http,
    Response,
    ResponseOptions,
    XHRBackend
} from '@angular/http';
import { BlogEntriesService } from './songhay-blog-entries.service';
import { BlogEntry } from '../models/songhay-blog-entry';
import { error } from 'util';

describe('BlogEntriesService', () => {
    const testBed = getTestBed();
    let service: BlogEntriesService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                BaseRequestOptions,
                BlogEntriesService,
                {
                    deps: [BaseRequestOptions],
                    provide: Http,
                    useFactory: (
                        backend: XHRBackend,
                        defaultOptions: BaseRequestOptions
                    ) => new Http(backend, defaultOptions)
                }
            ]
        });
    });

    it('should load index', done => {
        service = testBed.get(BlogEntriesService);
        expect(service).toBeDefined();
        expect(service).toBeTruthy();
        service
            .loadIndex()
            .then(result => {
                expect(result).toBeDefined();
            })
            .catch(result => expect(result).toBeUndefined())
            .then(done);
    });
});

I have removed the MockBackend code from my test because I think I do not need it because I am loading a local, static JSON file (not really a unit test). So the error I am getting is this:

TypeError: Cannot read property 'merge' of undefined

at mergeOptions (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/@angular/http/@angular/http.es5.js:1824:1)
    at Http.webpackJsonp.../../../http/@angular/http.es5.js.Http.get (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/@angular/http/@angular/http.es5.js:1924:1)
    at BlogEntriesService.webpackJsonp.../../../../../src/app/services/songhay-blog-entries.service.ts.BlogEntriesService.loadIndex (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/src/app/services/songhay-blog-entries.service.ts:78:14)
    at Object.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/src/app/services/songhay-blog-entries.service.spec.ts:39:14)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/zone.js/dist/zone.js:392:1)
    at ProxyZoneSpec.webpackJsonp.../../../../zone.js/dist/proxy.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/zone.js/dist/proxy.js:79:1)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/zone.js/dist/zone.js:391:1)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/zone.js/dist/zone.js:142:1)
    at Object.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/../angular.io-index-app/index-app/node_modules/zone.js/dist/jasmine-patch.js:102:1)
    at attemptAsync (http://localhost:9876/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?da99c5b057693d025fad3d7685e1590600ca376d:3945:24)

Is this issue here known? Should I just give up and build an e2e test?

1 Answer 1

1

The code has DI problems. Http factory has one dependency injected:

deps: [BaseRequestOptions],

While the factory expects 2 parameters, and they are mixed up.

Instead, it should be:

{
    deps: [XHRBackend, BaseRequestOptions],
    provide: Http,
    useFactory: (
        backend: XHRBackend,
        defaultOptions: BaseRequestOptions
    ) => new Http(backend, defaultOptions)
}

The only reason why Http provider is defined this way is that because usually the backend is replaced with MockBackend in unit tests. If this is not the case for integration test, HttpModule can be just imported instead.

Sign up to request clarification or add additional context in comments.

3 Comments

Http provider is redundant and can be omitted if If HttpModule has been imported.
I'll take a look at the Plunker you recommended and work my way toward my scenario as simply removing references to Http breaks things in ways I currently do not understand.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.