angular
angular copied to clipboard
APP_INITIALIZER contract not honoured with TestBed
I'm submitting a...
[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:
Current behavior
When importing a Module providing a promise-based APP_INITIALIZER into a TestBed, the tests are executed before the promise is fully resolved.
There was an issue for this very problem (#16204) but the reporter closed because he found a workaround.
Expected behavior
The promise of an APP_INITIALIZER should be fully resolved, exactly as when running the application that uses this module normally.
Minimal reproduction of the problem with instructions
Hadn't had the time, but I expect that it should be simple to know if is already implemented or not to behave like expected. If yes, I will produce a repro.
What is the motivation / use case for changing the behavior?
Same contract with tests or real app.
Environment
Angular version: 6.0.7
For the record, a solution until this is fixed, is to add the following beforeEach
in your jasmine tests (after compileComponents()
and before createComponent()
for example):
beforeEach(async () => {
// until https://github.com/angular/angular/issues/24218 is fixed
await TestBed.get(ApplicationInitStatus).donePromise;
});
@vicb are you expecting a repro before this is taken care of? Or is the angular team going to take a look directly at the code.
This doesn't seem to be a bug, regression or a corner case but a very clearly missing feature…
Any update on this?
P.s: @victornoel your workaround saved my day ; )
@vicb ping? :)
@vicb ping
This causes my app confusion regularly in testing. The errors are always so difficult to hunt down because they are cryptic, but I need APP_INITIALIZER to complete before the tests run.
I have been successfully using the workaround for this issue, but after updating to Angular 8 (currently on 8.0.6) it seems the workaround doesn't work anymore. I now have to resort to mocking out the services which should initialize on APP_INITIALIZER in all the unit tests which depend on it, which is quite a hassle.
@victornoel Thanks for the workaround. I wasted a day to get to this workaround. This issue still exists in Angular 8; its amazing how this looong pending issue hasn't been resolved yet!
Thumbs up to this - I would classify this as a bug rather than a feature request. Angular should use App Initializers in test the same way it does in serve/production without requiring the user to wait on the donePromise.
Just fyi - For angular 9, the workaround should use TestBed.inject() instead of TestBed.get(). And make sure it comes after TestBed.configureTestingModule(...)
I am using angular 6 and the suggested workaround by @victornoel isn't working for me. Any suggestions?
BTW, I am making Http calls inside the promise returned by APP_INITIALIZER's factory, and HttpClientTestingModule is injected in Testbed, i am guessing this could be the issue.
@podikris Did you find any solution / work around for this. I too have a situation like yours.
If you test with HttpClientTestingModule it is mandatory to flush each request manualy. To do so just inject HttpTestingController and flush the request like so:
const req = httpController.expectOne(<expected URL>);
req.flush(<request data goes here>);
also after each test make sure that you don't have outstanding requests with:
httpController.verify();
If you test with HttpClientTestingModule it is mandatory to flush each request manualy. To do so just inject HttpTestingController and flush the request like so:
const req = httpController.expectOne(<expected URL>); reqDef.flush(<request data goes here>);
also after each test make sure that you don't have outstanding requests with:
httpController.verify();
Sorry @copaste but issue is not related to HttpClientTestingModule
but taton APP_INITIALIZER
promise.
@meriturva Sorry it wasn't clear for me that is not related to HttpClientTestingModule
. Because If you have any http calls in the APP_INITIALIZER
the promise will never resolve until you flush it.
Up, spent 5 hours trying to understand why my tests were failing while the app was working.
Note, non-initializer providers are instantiated before for the initialization functions complete with victornoels workaround. This is still inconsistent with the actual application behavior.
There is no documentation on the pitfalls in testing if using APP_INITIALIZER. Even if the work around doesn't work for every user scenario, that this issue is outstanding for 5 years and there isn't even a mention outside of a ticket in GitHub is very frustrating when trying to figure out what is going wrong. For my case, the work around does get past the hurdle, so thanks to @victornoel for that!