简体   繁体   中英

Flutter - Mockito Firestore...get() - The method 'document' was called on null

for learning purposes I am trying to mock a Firestore controller class with Mockito.

firestore_controller.dart

import 'package:cloud_firestore/cloud_firestore.dart';


class FirestoreController implements FirestoreControllerInterface {

  final Firestore firestoreApi;
  FirestoreController({this.firestoreApi});

  @override
  Future<DocumentSnapshot> read() async {
    final DocumentSnapshot document = await this.firestoreApi.collection('user').document('user_fooBar').get();
    return document;
  }
}

firestore_controller_test.dart

import 'package:flutter_test/flutter_test.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:mockito/mockito.dart';
import 'package:fooApp/Core/repositories/firebase/firestore_controller.dart';

class MockFirestoreBackend extends Mock implements Firestore {}
class MockDocumentSnapshot extends Mock implements DocumentSnapshot {}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  group("Firebase Controller", () {

    final Firestore firestoreMock = MockFirestoreBackend();
    final MockDocumentSnapshot mockDocumentSnapshot = MockDocumentSnapshot();
    FirestoreController sut;

    test("try to read a document", () async {

      // Arrange
      final Map<String, dynamic> _fakeResponse = {
        'foo': 123,
        'bar': 'foobar was here',
      };

      sut = FirestoreController(firestoreApi: firestoreMock); // INJECT MOCK

      // Arrange: Mock
      when(firestoreMock.collection('user').document('user_fooBar').get()).thenAnswer((_) => Future<MockDocumentSnapshot>.value(mockDocumentSnapshot));
      when(mockDocumentSnapshot.data).thenReturn(_fakeResponse);

      // Act
      final fakeDocument = await sut.read();

    });
  });
}

🚨 Console Output 🚨

NoSuchMethodError: The method 'document' was called on null.
Receiver: null
Tried calling: document("user_fooBar")

sorry if the mistake is obvious, this is the first time I've used Mockito Where's my error? What do I miss? Thanks a lot!

try this:

https://pub.dev/packages/cloud_firestore_mocks

A test I've done using it:

class MockFirestore extends Mock implements Firestore {}
class MockDocument extends Mock implements DocumentSnapshot {}

void main() {
  final _tAppointmentModel = AppointmentModel(
    appointmentID: kAppointmentID,
    date: DateTime.parse("2020-12-05 20:18:04Z"),
    description: "test description",
    doctorID: kDoctorID,
    hospitalID: kHospitalID,
    infantID: kInfantID,
  );

  group('AppointmentModel tests: ', () {
    final tAppointmentID = kAppointmentID;
    final tInfantID = kInfantID;
    final tDoctorID = kDoctorID;
    final tHospitalID = kHospitalID;

    test('should be a subclass of Appointment', () async {
      expect(_tAppointmentModel, isA<Appointment>());
    });

    test('store and retrieve document from Firestore', () async {
      final instance = MockFirestoreInstance();
      await instance.collection('appointments').add({
        'appointmentID': tAppointmentID,
        'date': DateTime.parse("2020-12-05 20:18:04Z"),
        'description': "test description",
        'doctorID': tDoctorID,
        'hospitalID': tHospitalID,
        'infantID': tInfantID,
      });

      final snapshot = await instance.collection('appointments').getDocuments();
      final String expected = _tAppointmentModel.props[0];
      final String result = snapshot.documents[0].data['appointmentID'];
      expect(expected, result);
    });
  });
}

So I think I've found why this is - it appears to be a bug(ette) in Mockito, in that it doesn't handle the "dot walk" from collection(any) to document() or getDocuments(). I fixed it like this:

declare five classes:

class MockFirebaseClient extends Mock implements Firestore {} //for your mock injection

class MockCollectionReference extends Mock implements CollectionReference {} //for when declaration

class MockQuerySnapshot extends Mock implements QuerySnapshot {} //for the thenAnswer return on collection of docs

class MockDocumentReference extends Mock implements DocumentReference {} //for single doc query

class MockDocumentSnapshot extends Mock implements DocumentSnapshot {} // for the thenAnswer return on single doc query

Do your setup etc - then the when clauses are just:

when(mockCollectionReference.getDocuments())
         .thenAnswer((_) => Future.value(mockQuerySnapshot));  //for collection of docs query

when(mockDocumentReference.get())
            .thenAnswer((_) => Future.value(mockDocumentSnapshot)); //for single doc query 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM