Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to mock Firebase Auth but unsure how

I use Firebase to manage authentication within my app. This has a singleton object for the logged in user: Auth.auth().currentUser

In part of my code I check that the uid of the logged in user is equal to a userId associated with an object.

I need to test code that uses this check. For this I need to be able to inject a mock Firebase Auth object.

How can I mock the Firebase Auth object? Has anyone had experience with this before?

like image 815
Tometoyou Avatar asked Nov 22 '18 18:11

Tometoyou


People also ask

How do you mock Firebaseapp?

Copy the contents of: https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_auth/firebase_auth/test/mock.dart into a file, that you can import into your tests, where you need to initialize a Firebase app. Call setupFirebaseAuthMocks(); at the top of your main function for all your tests.

How can I check if the phone number already exists in the Firebase authentication?

In the Firebase console, open the Authentication section. In the Sign in method tab, enable the Phone provider if you haven't already. Open the Phone numbers for testing accordion menu. Provide the phone number you want to test, for example: +1 650-555-3434.


1 Answers

So I solved this by creating a few protocols for authentication and making User conform to that protocol:

protocol AuthUser {
    var uid: String {get}
    var displayName: String? {get}
    var email: String? {get}
    var photoURL: URL? {get}
}

extension User : AuthUser {}

protocol AuthenticationProtocol {
    var currentUser: AuthUser? {get}
}

Then I created an Authentication class that conforms to the AuthenticationProtocol:

final class Authentication: AuthenticationProtocol {
    static let shared = Authentication()
    private let auth = Auth.auth()
    var currentUser: AuthUser? {
        return auth.currentUser
}

When I have a class that needs authentication in my app I inject a class that conforms to AuthenticationProtocol like this:

final class MyClass {
    private let auth: AuthenticationProtocol

    init(auth: AuthenticationProtocol = Authentication.shared) {
        self.auth = auth
}

Then I can get the id of the current logged in user by calling auth.currentUser?.uid.

For tests I then create a mock class that conforms to AuthenticationProtocol like this:

final class AuthenticationMock : AuthenticationProtocol {
    private let uid: String
    let currentUser: AuthUser?

    init(currentUser: AuthUser) {
        self.currentUser = currentUser
    }
}

And then I can inject that when I call MyClass(auth: <Authentication Mock Instance>)

like image 158
Tometoyou Avatar answered Oct 18 '22 00:10

Tometoyou