覆盖TestBed提供者以进行特定测试

时间:2019-10-30 17:34:22

标签: angular dependency-injection

我有一个组件,该组件具有两个依赖项:一个是LOCALE_ID全局定义的角度,另一个是语言,在组件中定义为{ provide: LANGUAGE_TOKEN, useValue: navigator.language }

对于测试,我都将所有测试都覆盖在TestBed中,因此在进行业力测试时测试不会从Chrome浏览器中注入任何东西,并且测试不会因测试环境而异:

TestBed.configureTestingModule({
  declarations: [
    MyComponent, RouterStubComponent,
  ],
  imports: [
    MatToolbarModule, RouterTestingModule, MatIconModule, MatButtonModule,
  ],
  providers: [
    {provide: LOCALE_ID, useValue: 'en-US' },
  ]
}).compileComponents();

TestBed.overrideProvider(LOCATION_TOKEN, {useValue: locationStub});
TestBed.overrideProvider(LANGUAGE_TOKEN, {useValue: 'en-US' });

现在,组件中有一些逻辑,这些逻辑取决于语言环境和浏览器语言,因此我需要对它们进行模拟。 LANGUAGE_TOKEN的模拟非常简单,不便之处:

 it('should redirect to spanish when in spanish browser', () => {
    TestBed.overrideProvider(LANGUAGE_TOKEN, {useValue: 'es'});
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

    expect(hrefSpy.calls.count()).toBe(1);
    expect(hrefSpy.calls.argsFor(0)[0]).toEqual(environment.spanUrl);
  });

但是用相同的代码覆盖LOCALE_ID无效。

  it('should ...', () => {
    TestBed.overrideProvider(LOCALE_ID, {useValue: 'es-ES'});
    console.log(TestBed.get(LOCALE_ID)); // en-US!!!!
    fixture = TestBed.createComponent(MamanComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

    expect(hrefSpy.calls.count()).toBe(1); //FAIL
    expect(hrefSpy.calls.argsFor(0)[0]).toEqual(environment.engUrl);//FAIL
  });

我也无法在this question中找到有效的答案。

1 个答案:

答案 0 :(得分:2)

这是因为,一旦您调用compileComponents,这些提供程序就会被冻结,并且不会被覆盖。

从提供者中删除LOCALE_ID,以便其值不被冻结。 (但请确保在创建组件实例之前,使用overrideProviders提供它)

TestBed.configureTestingModule({
  declarations: [
    MyComponent, RouterStubComponent,
  ],
  imports: [
    MatToolbarModule, RouterTestingModule, MatIconModule, MatButtonModule,
  ],
  providers: [
    --> remove 
  ]
}).compileComponents();

TestBed.overrideProvider(LOCALE_ID, {useValue: 'es-ES'});
//Add it before creating component, to have a default value in each test, add it in a beforeEach block.

OR

您可以在每个测试中创建组件实例之前调用compileComponents。

TestBed.configureTestingModule({
  declarations: [
    MyComponent, RouterStubComponent,
  ],
  imports: [
    MatToolbarModule, RouterTestingModule, MatIconModule, MatButtonModule,
  ],
  providers: [
    {provide: LOCALE_ID, useValue: 'en-US' },
  ]
});
--> remove compileComponents

然后在每个测试中:

it('should ...', () => {
    TestBed.overrideProvider(LOCALE_ID, {useValue: 'es-ES'});
    // Add here
    TestBed.compileComponents();
    fixture = TestBed.createComponent(MamanComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

    expect(hrefSpy.calls.count()).toBe(1); //FAIL
    expect(hrefSpy.calls.argsFor(0)[0]).toEqual(environment.engUrl);//FAIL
  });