Skip to content

Instantly share code, notes, and snippets.

@utkarsh-UK
Last active January 25, 2024 08:02
Show Gist options
  • Select an option

  • Save utkarsh-UK/1a1d2c25fad9cbbc19df5c3a26655a82 to your computer and use it in GitHub Desktop.

Select an option

Save utkarsh-UK/1a1d2c25fad9cbbc19df5c3a26655a82 to your computer and use it in GitHub Desktop.
import 'package:cloud_firestore/cloud_firestore.dart';
class MockFirestore extends Mock implements FirebaseFirestore {}
class MockCollectionReference extends Mock implements CollectionReference {}
class MockDocumentReference extends Mock implements DocumentReference {}
class MockDocumentSnapshot extends Mock implements DocumentSnapshot {}
void main() {
MockFirestore instance;
MockDocumentSnapshot mockDocumentSnapshot;
MockCollectionReference mockCollectionReference;
MockDocumentReference mockDocumentReference;
setUp(() {
instance = MockFirestore();
mockCollectionReference = MockCollectionReference();
mockDocumentReference = MockDocumentReference();
mockDocumentSnapshot = MockDocumentSnapshot();
});
//Get data from firestore doc
test('should return data when the call to remote source is successful.', () async {
when(instance.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.get()).thenAnswer((_) async => mockDocumentSnapshot);
when(mockDocumentSnapshot.data()).thenReturn(responseMap);
//act
final result = await remoteDataSource.getData('user_id');
//assert
expect(result, userModel); //userModel is a object that is defined. Replace with you own model class object.
});
//Add data to firestore doc
//This demonstrates chained call like (instance.collection('path1').doc('doc1').collection('path2').doc('doc2').add(data));
//We return the same mocked objects for each call.
test('should get data from nested document.', () async {
// arrange
when(instance.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.add(any)).thenAnswer((_) async => mockDocumentReference);
when(mockDocumentReference.id).thenReturn(messageID);
when(mockDocumentSnapshot.data()).thenReturn(messageData);
//act
final result = await remoteDataSource.addData(userID, notificationID);
//assert
expect(result, notificationID);
});
//Get list of documents from firestore.
test('should get list of all the documents.', () async {
// arrange
when(instance.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.get()).thenAnswer((_) async => mockDocumentSnapshot);
when(mockDocumentSnapshot.data()).thenReturn(roomsMap);
when(mockDocumentReference.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.get()).thenAnswer((_) async => mockQuerySnapshot);
when(mockQuerySnapshot.docs).thenReturn([mockQueryDocumentSnapshot]);
when(mockQueryDocumentSnapshot.data()).thenReturn(membersMap);
//act
final result = await remoteDataSource.fetchUsers();
//assert
expect(result, users);
});
//Delete doc in firestore.
test('should delete a doc and return true.', () async {
// arrange
when(instance.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.delete()).thenAnswer((_) async => Future.value());
//act
final result = await remoteDataSource.joinSquad();
//assert
expect(result, true);
});
//Mock query methods like orderBy(), limit().
test('should return previous messages when getting data is successful.', () async {
// arrange
when(instance.collection(any)).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.collection('messages')).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(lastMessageID)).thenReturn(mockDocumentReference);
when(mockDocumentReference.get()).thenAnswer((realInvocation) async => mockDocumentSnapshot);
when(mockCollectionReference.orderBy('timestamp', descending: true)).thenReturn(mockQuery);
when(mockQuery.startAfterDocument(mockDocumentSnapshot)).thenReturn(mockQuery);
when(mockQuery.limit(20)).thenReturn(mockQuery);
when(mockQuery.get()).thenAnswer((_) async => mockQuerySnapshot);
when(mockQuerySnapshot.docs).thenReturn([mockQueryDocumentSnapshot]);
when(mockQueryDocumentSnapshot.data()).thenReturn(message);
//act
final result = await remoteDataSource.loadPreviousMessages(roomID: roomID, lastFetchedMessageID: lastMessageID);
//assert
expect(result, messages);
});
}
@Babwenbiber
Copy link

I figured it out how to use your implementation In null-safety and with the code generation of Mockito.

Code gen:

Map<String, bool> getData() {
  return {}; //this will be overriden
}

@GenerateMocks(
  [
    FirebaseFirestore,
    CollectionReference,
    DocumentReference,
    QuerySnapshot,
  ],
  customMocks: [
    MockSpec<QueryDocumentSnapshot>(
        as: #MockQueryDocumentSnapshot, fallbackGenerators: {#data: getData}),
  ],
)

Then in your declaration of your mocked vars you need to tell the compiler what you are actually extending:

late MockFirebaseFirestore firestore;
late MockCollectionReference<Map<String, dynamic>> userCollection;
late MockDocumentReference<Map<String, dynamic>> doc;
late MockCollectionReference<Map<String, dynamic>> notificationCollection;
late MockQuerySnapshot<Map<String, dynamic>> querySnapshot;
late MockQueryDocumentSnapshot<Map<String, dynamic>> queryDocumentSnapshot;
...
setState 
...

Here is a usage of my mocked methods:

when(firestore.collection("users")).thenReturn(userCollection);
when(userCollection.doc("1")).thenReturn(doc);
when(doc.collection("notifications")).thenReturn(notificationCollection);
when(notificationCollection.get()).thenAnswer((_) async => querySnapshot);
when(querySnapshot.docs)
          .thenAnswer((realInvocation) => [queryDocumentSnapshot]);
when(queryDocumentSnapshot.data())
          .thenAnswer((realInvocation) => {"message": true});

To understand why the custom mock is needed read this issue and the readme of the Mockito repo.

Hope that helps anyone.

@sath26
Copy link

sath26 commented Sep 16, 2021

when(instance.collection("sold")).thenReturn(mockCollectionReferenceSold);
    when(mockCollectionReferenceSold.doc("abc"))
        .thenReturn(mockDocumentReferenceSold);
   
    when(mockDocumentReferenceSold.set({
      'appointmentID': "tAppointmentID",
      'date': DateTime.parse("2020-12-05 20:18:04Z"),
      'description': "test description",
    })).thenAnswer((_) async => mockDocumentSnapshotSold);

    print(mockDocumentSnapshotSold.id);

prints null

any idea?
why data hasnt inserted into firestore?

@Babwenbiber
Copy link

If what You write is your whole code, then you are refering to mockDocumentSnapshotSold.id, but didn't call mockDocumentReferenceSold

@sath26
Copy link

sath26 commented Sep 17, 2021

@Babwenbiber could u show in code how and where it shoudl be called? i am not getting you.

@sumanpdneupane
Copy link

I am also stuck in the same as @sath26.
prints null

sath26 commented on Sep 16 •
when(instance.collection("sold")).thenReturn(mockCollectionReferenceSold);
when(mockCollectionReferenceSold.doc("abc"))
.thenReturn(mockDocumentReferenceSold);

when(mockDocumentReferenceSold.set({
  'appointmentID': "tAppointmentID",
  'date': DateTime.parse("2020-12-05 20:18:04Z"),
  'description': "test description",
})).thenAnswer((_) async => mockDocumentSnapshotSold);

print(mockDocumentSnapshotSold.id);

prints null

any idea?
why data hasnt inserted into firestore?

@sumanwebidigital
Copy link

How can we test streams in firestore and model class.
//arrange
when(instance.collection("todos")).thenReturn(mockCollectionReference);
when(mockCollectionReference.doc(any)).thenReturn(mockDocumentReference);
when(mockDocumentReference.collection("todos"))
.thenReturn(mockCollectionReference);
when(mockCollectionReference.snapshots())
.thenReturn(mockQuerySnapshotStream);
when(await mockQuerySnapshotStream.toList())
.thenReturn(mockQuerySnapshotList);
when(mockQuerySnapshotList.map((e) {
final List retVal = [];
for (final DocumentSnapshot doc in e.docs) {
retVal.add(TodoModel.fromDocumentSnapshot(documentSnapshot: doc));
}
return retVal;
}));

  //test
  int i = 0;
  stream.listen(
    expectAsync1((event) {
      expect(event.content, actual[i].content);
      i++;
    }, count: take),
  );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment