0

Given the example spec test below

beforeEach(function () {
        TestBed.configureTestingModule({
            providers: [
                { provide: TranslateService, useClass: TranslateServiceMock },
                { provide: StoreService, useClass: StoreServiceMock },
                {
                    provide: GLOBAL_CONFIG_TOKEN,
                    useValue: { default: true }
                }
            ],
        });
        let config = TestBed.inject(GLOBAL_CONFIG_TOKEN);
});

it('should override provider otherwise what is the point? :)', () => {
  let config = TestBed.overrideProvider(GLOBAL_CONFIG_TOKEN, { useValue: { default: false, random: 'damn' } });
expect(config).toEqual({default: false, random: 'damn'});
});

the thing is that test failed because default is always true and random is not a property of config. This means that config still has the default value during the configure of Testing Module and the provider hasn't been overridden.

Any idea why? Is overrideProvider method just a helper that updates the moduleRef object initially passed at configureTestingModule?

Rambou
  • 968
  • 9
  • 22

2 Answers2

1

That's right because there're built-in functions that trigger compilation of the test module. If you want to update the value after you need to reset the testBed, it's doable only via accessing private properties and therefore not recommended, better would be to write a proper test when env is created first and then its data is fetched.

Nevertheless that's what you can do before TestBed.overrideProvider to make it work.

  (getTestBed() as any)._instantiated = false;
  (getTestBed() as any)._moduleFactory = undefined;
satanTime
  • 12,631
  • 1
  • 25
  • 73
  • Thanks, indeed. Btw, I still believe that this function shouldn't have been just a helper to update TestBed before instantiation; it's my personal opinion, though, but semantically doesn't seem reasonable to me. :/ Maybe I'll open an issue for on Github repo :) – Rambou Jun 02 '20 at 06:32
  • 1
    totally agree, I did an investigation long time ago when found this solution and was surprised too, it should definitely be more flexible. – satanTime Jun 02 '20 at 06:35
-1

As it seems the fact that TestBed.inject is running before TestBed.overrideProvider causes overrideProvider to not have any effect. The overrideProvider function should be used before TestBed.inject(). Apparently it seems that is just a helper method after configurTestingModule() function run. So a solution to the example above would be:

beforeEach(function () {
        TestBed.configureTestingModule({
            providers: [
                { provide: TranslateService, useClass: TranslateServiceMock },
                { provide: StoreService, useClass: StoreServiceMock },
                {
                    provide: GLOBAL_CONFIG_TOKEN,
                    useValue: { default: true }
                }
            ],
        });
});

it('should override provider otherwise what is the point? :)', () => {
  TestBed.overrideProvider(GLOBAL_CONFIG_TOKEN, { useValue: { default: false, random: 'damn' } });

  let config = TestBed.inject(GLOBAL_CONFIG_TOKEN);
  expect(config).toEqual({default: false, random: 'damn'});
});
Rambou
  • 968
  • 9
  • 22