lundi 18 septembre 2017

Angular 2 - How to Override a Dependency in Another Module for Testing

I'm trying to test a service in my module that depends on services in another module. The other module's services, components...are accessed via npm packages. My company, like most is a bit finicky about putting source code on the web so hopefully I've posted enough to get help.

The service that I want to mock get's user information and exists in another module. I get an error saying that a property that is returned by this service is undefined. I tried using TestBed.overrideModule to change the provider in the other module to a mock version that I created. I'm having trouble finding documentation for overrideModule and I've tried for a couple of days now and can't figure out how to make what I want work, even after finding a few usages of overrideModules. Any help would be appreciated.

Based on the error I get, I'm wondering if the correct dependency is being injected but don't really know how to check. The error stack trace point to the equivalent of webpack:///node_modules/@another-repo/prefs/index.js.

Code (please let me know if you have questions I tried to strip out things that would identify my company):

The following are in my module

// classa.service.ts
import { Injectable } from '@angular/core';
import { IDModel } from '@another-repo/core';
import { FormatService } from '@another-repo/prefs';
import { MyRepo } from './my-repo.service';

@Injectable()
export class ClassA {
    constructor(idModel: IDModel, repo: MyRepo, formats: FormatService) {

    }
    doSomething() { }
}
// in my module
// my-repo.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';

@Injectable()
export class MyRepo {
    constructor(private readonly http: Http) {
    }

    get(id): Observable<any> {
        return this.http
            .get(api(`${id}`))
            .map(response => response.json());
    }
}

// my-repo-service.spec.ts
//...
describe('test', () => {
    let testService;
    beforeEach(async () => {
        TestBed.configureTestingModule({
            imports: [
                HttpModule,
                FooModule
            ],
            providers: [
                { provide: RepoToMock1, useClass: MockRepoToMock1 },
                MyRepo,
            ],
        });

        TestBed.overrideModule(FooModule,
            {
                remove: {
                    providers: [RepoToMock1]
                },
                add: {
                    providers: [{ provide: RepoToMock1, useClass: MockRepoToMock1 }]
                }
            });
    });

    beforeEach(() => {
        testService = TestBed.get(MyRepo);
    });
    //...
});  

this is in the index.d.ts file in node_modules let's call the module FooModule

export class IDModel {
    id: Observable<number>;
    constructor(otherIdRepo: OtherIdRepo, otherType: OtherTypeModel);
}

export class FormatService {
    constructor(formatModel: FormatModel, timeService: TimeService, numberService, NumberService);
}

export class FormatModel {
    myFormat: Format;
    constructor(repo: RepoToMock1);
}

export class Format {
    branding: string;
}

export class RepoToMock1 {
    constructor(http: Http);
    getPrefs(): Observable<Format>;
}

export class TimeService {
    constructor(formatModel: FormatModel);
}

export class NumberService {
    getNumber();
} 

Aucun commentaire:

Enregistrer un commentaire