简体   繁体   中英

Override testbed provider to use other inject value in unit test

I am trying to override testbed provider because I have to test for the two scenarios in which the value I am injecting into the modal are different.

I have tried something like this till now but had no luck.

  theTestBed.overrideProvider('content', { useValue: 'Pending' });
  theTestBed.compileComponents();
  fixture = theTestBed.createComponent(RequestChangeStatusModalComponent);
  component = fixture.componentInstance;
  component.ngOnInit();
  fixture.changeDetectorRef.detectChanges();
  fixture.detectChanges();
  statusOptions = component.changeStatusData.statusOptions;
  expect(statusOptions[0]).toBe('Budgeted Line Item');
  expect(statusOptions[1]).toBe('Considered for Board');

The situation is that I have a modal component to which I am injecting requestType parameter.

    @Inject('content') private requestType: string

In ngOnInit(), I am setting dropdown options depending upon what the requestType is.

Now, I am writing unit tests for the component. There are two values for requestType - Approved and Pending .

So, I am passing the Approved value to the modal when I am initializing the testbed.

theTestBed = TestBed.configureTestingModule({
  declarations,
  imports,
  [{
    provide: 'content',
    useValue: 'Approved'
  }]
});

But the thing is how do I reset the provider to pass the other requestType as Pending to the modal?

Can anyone tell me how can I achieve the desired outcome?

Maybe I can test what I am testing without overriding provider?

If it is a provider declared on a module level you can try to 'override' it during the configureTestingModule() call and remove the overrideProvider() call:

  TestBed.configureTestingModule({
    imports:   [],
    declarations: [RequestChangeStatusModalComponent],
    providers: [
      { provide: 'content', useValue: 'Pending'}
    ]
  });
  TestBed.compileComponents();

If it is a service provider that is declared on a component level you will have to use overrideComponent to be able to ovveride its providers:

  TestBed.configureTestingMod
  TestBed.overrideComponent(HeroDetailComponent, {
    set: {
      providers: [
        { provide: HeroDetailService, useClass: HeroDetailServiceSpy }
      ]
    }
  })

UPDATE Moving the createComponent() from the beforeEach into every it testcase did solve the problem in my test scenario.

  beforeEach(() => {
    // the createComponent() in the beforeEach causes the problem 
    //
    // fixture = TestBed.createComponent(FlightSearchComponent);
    // component = fixture.componentInstance;
    // fixture.detectChanges();
  });

  it('should use content Pending', () => {
    fixture = TestBed.createComponent(FlightSearchComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    expect(component.value).toBe('Pending');
  });

  it('should use content Approved', () => {
    TestBed.overrideProvider('content', { useValue: 'Content 2'});
    fixture = TestBed.createComponent(FlightSearchComponent);
    fixture.detectChanges();
    expect(component.value).toBe('Approved');
  });

The problem is that with two calls to createComponent the second call is using already instantiated ComponentFactories and ModuleFactories.

We can see that very good in the Angular source of TestBed itself:

  createComponent<T>(component: Type<T>): ComponentFixture<T> {
    this._initIfNeeded();
    ..
  }

  private _initIfNeeded(): void {
    if (this._instantiated) {
      return;
    }
    ..
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM