Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter FirebaseAuth unit testing

I'm trying to test my whole AuthManager class which use FirebaseAuth to signin, login. Here my file:

    class AuthManager extends ChangeNotifier {
      final FirebaseAuth auth;
    
      Stream<User?> get user => auth.authStateChanges();
    
      static Future<FirebaseApp> initializeFirebase({
        required BuildContext context,
      }) async {
        FirebaseApp firebaseApp = await Firebase.initializeApp();
    
        return firebaseApp;
      }
    
      AuthManager({required this.auth});
    
      Future<String> signup(String email, String password) async {
        try {
          final credential = await auth.createUserWithEmailAndPassword(
            email: email,
            password: password,
          );
          return "Success";
        } on FirebaseAuthException catch (e) {
          rethrow;
        }
      }
    
      Future<String> signInWithEmailAndPassword(
          String email, String password) async {
        try {
          final userCredential = await auth.signInWithEmailAndPassword(
              email: email, password: password);
          return "Success";
        } on FirebaseAuthException catch (e) {
          return "Failed";
        } catch (e) {
          rethrow;
        }
      }
    
      static Future<String> signOut() async {
        try {
          await FirebaseAuth.instance.signOut();
          return "Success";
        } catch (e) {
          rethrow;
        }
      }
    }

I used to return the usercredential but wanted to try test a simple string return for the test, following this tutorial: https://www.youtube.com/watch?v=4d6hEaUVvuU, here is my test file

import 'package:firebase_auth/firebase_auth.dart';
import 'package:notes_firebase_app/data/models/auth_manager.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

class MockFirebaseAuth extends Mock implements FirebaseAuth {
  @override
  Stream<User> authStateChanges() {
    return Stream.fromIterable([
      _mockUser,
    ]);
  }
}

class MockUser extends Mock implements User {}

final MockUser _mockUser = MockUser();

class MockUserCredential extends Mock implements Future<UserCredential> {}

void main() {
  final MockFirebaseAuth mockFirebaseAuth = MockFirebaseAuth();
  final AuthManager authManager = AuthManager(auth: mockFirebaseAuth);
  final MockUserCredential mockUserCredential = MockUserCredential();
  setUp(() {});
  test("emit occurs", () async {
    expectLater(authManager.user, emitsInOrder([_mockUser]));
  });

  test("create account", () async {
    when(mockFirebaseAuth.createUserWithEmailAndPassword(
            email: "[email protected]", password: "123456"))
        .thenAnswer((realInvocation) => null);

    expect(
        await authManager.signInWithEmailAndPassword(
            "[email protected]", "123456"),
        "Success");
  });
}

I face two problems here, cannot pass null because we need to handle it now or this throw this error

The return type 'Null' isn't a 'Future<UserCredential>', as required by the closure's context

Then I tried to mock UserCredential like this.

  final MockUserCredential mockUserCredential = MockUserCredential();

    when(mockFirebaseAuth.createUserWithEmailAndPassword(
            email: "[email protected]", password: "123456"))
        .thenAnswer((realInvocation) => mockUserCredential);

but I'm getting this error:

type 'Null' is not a subtype of type 'Future<UserCredential>'

What am I doing wrong ? Help will be much appreciated.

like image 671
Willy Kim Avatar asked Oct 16 '25 06:10

Willy Kim


1 Answers

I am not totally sure but mockito package may need a generator. Try mocktail package and use

when(()=> mockFirebaseAuth.createUserWithEmailAndPassword(
email: "[email protected]", password: "123456")).thenAnswer((realInvocation) => null);

use callback function in when().

like image 79
metinbeycigim Avatar answered Oct 18 '25 00:10

metinbeycigim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!