Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 560
Joe Attardi Avatar asked May 10 '18 00:05

Joe Attardi


2 Answers

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!

like image 170
Rukshan Dangalla Avatar answered Jan 17 '23 03:01

Rukshan Dangalla


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);
  });
});
like image 38
obaylis Avatar answered Jan 17 '23 03:01

obaylis