Reputation: 2169
I have this basic code in a service that I want to test, using Jasmine, Karma and, whenever convenient, ng-mocks.
const app = initializeApp(environment.firebase);
this.auth = getAuth(app);
this.db = getDatabase();
// set up auth state listener
onAuthStateChanged(this.auth, (user) => {
// ...
});
I want to mock onAuthStateChanged
in a way, that in one spec, it "returns" a mocked user instace, so it fakes being logged in, and in another spec, it returns null, meaning we are not logged in.
The problem is that these methods are not used via Dependency Injection but simply by importing:
import { Auth, getAuth, onAuthStateChanged, User } from '@angular/fire/auth';
They are declared in index.d.ts
like so:
declare module "@firebase/auth" {
...
function onAuthStateChanged(auth: types.FirebaseAuth, nextOrObserver: NextOrObserver<User>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
...
}
And because of that, I just can't figure out how to mock them. I've been wasting my past couple days to figure this out, thank you very much!
Upvotes: 1
Views: 105
Reputation: 75
Create a new service for the "firebase/auth"
elements.
You can then easily mock your service with jasmine.createSpyObj
.
For example, your service could look like:
import { Injectable } from "@angular/core";
import { getAuth, User } from "firebase/auth";
@Injectable({
providedIn: "root",
})
export class FirebaseService {
/** Get the current FirebaseAuth user */
async getUser(): Promise<User | null> {
const auth = getAuth();
return new Promise((resolve) => {
auth.onAuthStateChanged((user: User | null) => {
resolve(user);
});
});
}
}
Then in your tests (in the spec for the component/service that imports your FirebaseService):
beforeEach(waitForAsync(() => {
firebaseServiceMock = jasmine.createSpyObj("FirebaseService", ["getUser"]);
TestBed.configureTestingModule({
imports: [YourPage],
providers: [
{ provide: FirebaseService, useValue: firebaseServiceMock },
],
schemas: [NO_ERRORS_SCHEMA], // Ignore external template dependencies
}).compileComponents();
fixture = TestBed.createComponent(YourPage);
component = fixture.componentInstance;
}));
it("mock service should return a user", (done) => {
// Mock the getUser method, add whatever you need from the firebase/auth User
const mockUser: any = { email: "[email protected]" };
firebaseServiceMock.getUser.and.returnValue(mockUser);
// Your test that utilises the result of the firebase getAuth user
const result = component.doSomething();
expect(result.email).toBe("[email protected]");
});
Upvotes: 0