如何在测试角度2组件时模拟@injected服务?

时间:2018-04-18 16:05:42

标签: angular testing dependency-injection jasmine

我有一个带签名的组件:

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

组件的spec文件设置为:

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();
});

但是,由于@Inject装饰器,未使用提供程序,测试在运行时失败:

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

如果在组件中使用@Injected,我如何强制TestingModule使用mockSitService?

1 个答案:

答案 0 :(得分:2)

正如评论中所述,当使用Angular的DI设置服务时,Angular需要@Inject(...)中的任何标记与provide属性的标记相同。这也意味着注入令牌应该导出模块外部,以便其他人使用@Inject()语法。

如果提供的服务如下:

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

然后@Inject()应该像这样设置(使用相同的注入令牌):

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

因此,在您的测试中,您通过(再次使用相同的注入令牌)模拟它:

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

有关注射令牌的更多信息,请参阅Angular docs