typescript - Hur man mockar en @injected-tjänst när man testar en Angular 2-komponent?


Jag har en komponent med signaturen:

constructor(private loremApiService: LoremApiService,
      private ipsumService: IpsumService,
      private dolorService: DolorService,
      @Inject('sitService') private sitService: library.service.Service) {
}

Specfilen för komponenten är inställd med:

let component: PowerBiReportComponent;
let fixture: ComponentFixture<TestingComponent>;
const mockLoremApi = { methodThatIsCalled: () => {} };
const mockIpsumService = { };
const mockSitService = { };

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [ TestingComponent ],
        schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
        providers: [
            { provide: LoremApiService, useValue: mockLoremApi },
            { provide: IpsumService, useValue: mockIpsumService },
            UnmockedService,
            { provide: library.service.Service, useValue: mockSitService }
        ]
    })
    .compileComponents();
}));

beforeEach(() => {
    fixture = TestBed.createComponent(TestingComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
});

Men leverantören används inte, på grund av @Inject-dekoratorn, testet misslyckas vid körning med:

Error: StaticInjectorError(DynamicTestModule)[sitService]: 
  StaticInjectorError(Platform: core)[sitService]: 
  NullInjectorError: No provider for sitService!

Hur tvingar jag TestingModule att använda mockSitService trots att det är @Injected i komponenten?

Svar #1

Som nämnts i kommentarerna behöver Angular att den token som finns i @Inject(...) är densamma som den som anges för provide-egenskapen när tjänsten konfigureras med Angulars DI. Detta innebär också att injektionstoken bör exporteras utanför modulen för att andra ska kunna använda @Inject()-syntaxen.

Om tjänsten tillhandahålls på detta sätt:

@NgModule({
    providers: [
        { provide: SERVICE_TOKEN, useClass: Service }
    ]
})

Då ska @Inject() ställas in på detta sätt (med samma injektionstoken):

constructor(@Inject(SERVICE_TOKEN) private service: Service) {
}

Så, i ditt test mockar du det via (igen, med samma injektionstoken):

beforeEach(async(() => {
    TestBed.configureTestingModule({
        providers: [
            { provide: SOME_TOKEN, useValue: mockService }
        ]
    })
    .compileComponents();
}));

För mer information om injektionstoken, se Angular-dokumentationen.

Relaterade artiklar