'NullInjectorError: No provider for StateObservable when using ng-packagr
I have an Angular 5 project that uses ngrx/store. The project consists of an application and a shared library that the application uses. Up until today, we had been compiling the TypeScript for both projects together - the library was being "published" with just the TypeScript code.
Today, I got this library working with ng-packagr
and pulled it in to the application using yarn link
, so that I could run the local code. However, when I try to start my app, I get this error in the browser:
Unhandled Promise rejection: StaticInjectorError(AppModule)[Store -> StateObservable]:
StaticInjectorError(Platform: core)[Store -> StateObservable]:
NullInjectorError: No provider for StateObservable! ; Zone: <root> ; Task: Promise.then ; Value: Error: StaticInjectorError(AppModule)[Store -> StateObservable]:
StaticInjectorError(Platform: core)[Store -> StateObservable]:
NullInjectorError: No provider for StateObservable!
at _NullInjector.get (core.js:1002)
at resolveToken (core.js:1300)
at tryResolveToken (core.js:1242)
at StaticInjector.get (core.js:1110)
at resolveToken (core.js:1300)
at tryResolveToken (core.js:1242)
at StaticInjector.get (core.js:1110)
at resolveNgModuleDep (core.js:10854)
at _createClass (core.js:10895)
at _createProviderInstance$1 (core.js:10865)
I have no idea where this is error coming from. My only clue is that it mentions AppModule
. In my AppModule
, I am importing @ngrx/store
and importing StoreModule.forRoot
into my module.
Solution 1:[1]
Here is how I fixed the issue in my case:
I Imported the following:
import { Store } from '@ngrx/store';
import { StoreModule } from '@ngrx/store';
I added the store module in imports as : imports: [StoreModule.forRoot({}),............
Then I added the store service to the providers : providers: [Store]
Key point is to check missing providers. Hope this helps!
Solution 2:[2]
As this is a relatively old question, it is possible with NgRx 7 onwards to use MockStore.
See use of ProvideMockStore in providers array below. MockStore can be used to set state as per your test's requirements.
See NgRx Testing - Using a Mock Store - their example:
import { TestBed } from '@angular/core/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { cold } from 'jasmine-marbles';
import { AuthGuard } from '../guards/auth.guard';
describe('Auth Guard', () => {
let guard: AuthGuard;
let store: MockStore;
const initialState = { loggedIn: false };
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
// any modules needed
],
providers: [
AuthGuard,
provideMockStore({ initialState }),
// other providers
],
});
store = TestBed.inject(MockStore);
guard = TestBed.inject(AuthGuard);
});
it('should return false if the user state is not logged in', () => {
const expected = cold('(a|)', { a: false });
expect(guard.canActivate()).toBeObservable(expected);
});
it('should return true if the user state is logged in', () => {
store.setState({ loggedIn: true });
const expected = cold('(a|)', { a: true });
expect(guard.canActivate()).toBeObservable(expected);
});
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Rukshan Dangalla |
Solution 2 | obaylis |