I am trying to use Karma and Jasmine to test my Angular5 that uses Firestore. However when I do "ng test", I get an error saying "NullInjectorError: No provider for AngularFirestore/AngularFireAuth/AuthService!". Following the post at NullInjectorError: No provider for AngularFirestore, I added AngularFirestore, AngularFireAuth, and AuthService to provider in app.module.ts, but that did not resolve the issue.
app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AuthService} from './core/auth.service';
// Routing and routes import
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
// Authentication Module
import { CoreModule } from './core/core.module';
// Firebase imports
import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import { AngularFirestoreModule } from 'angularfire2/firestore';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireStorageModule } from 'angularfire2/storage';
import { UserProfileComponent } from './user-profile/user-profile.component';
import { ProjectsComponent } from './projects/projects.component';
import { AngularFirestore } from 'angularfire2/firestore';
@NgModule({
declarations: [
AppComponent,
UserProfileComponent,
ProjectsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase, "life-planner"),
AngularFirestoreModule,
AngularFireAuthModule,
AngularFireStorageModule,
FormsModule,
CoreModule,
AuthService,
AngularFirestore,
AngularFireAuth
],
providers: [
AngularFirestore,
AuthService,
AngularFireAuth,
],
bootstrap: [AppComponent]
})
export class AppModule { }
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"paths": {
"@angular/*": [
"../node_modules/@angular/*"
]
},
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}
app.component.spec.ts (the code for tests):
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { RouterTestingModule } from '@angular/router/testing';
import {
AngularFirestore,
AngularFirestoreCollection,
AngularFirestoreDocument
} from 'angularfire2/firestore';
import { NgModule } from '@angular/core';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AppComponent ],
imports: [
RouterTestingModule
]
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});
Any help is appreciated, thanks in advance.
The service AngularFirestore relies on initialization of AngularFireModule and import of AngularFirestoreModule which you have done for your actual code.
For the test, you don't have that setup. Which is correct in the sense that ideally you shouldn't call out to actual firestore database from your test. So the solution is you need to stub the service.
const FirestoreStub = {
collection: (name: string) => ({
doc: (_id: string) => ({
valueChanges: () => new BehaviorSubject({ foo: 'bar' }),
set: (_d: any) => new Promise((resolve, _reject) => resolve()),
}),
}),
};
Add whatever the methods you are using, this example doesn't have all available methods stubbed.
Then provide that stub:
TestBed.configureTestingModule({
providers: [
{ provide: AngularFirestore, useValue: FirestoreStub },
],
});
Credit goes to @ksaifullah
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With