mock_cloud_firestore 0.0.20

Flutter Android iOS web

Easier way to mock cloud_firestore, without using `Firestore.channel.setMockMethodCallHandler`

Mock Cloud Firestore

The best way i found to test cloud_firestore is to use Firestore.channel.setMockMethodCallHandler. But this requires knowledge of firebase protocol. This implementation tries to provide easier way.

First define the firestore data as json #

  String source = r"""
{
  "goals": {
    "1": {
      "$": "Goal",
      "id": "1",
      "taskId": "1",
      "projectId": "1",
      "profileId": "1",
      "state": "ASSIGNED"
    }
  },
  "projects": {
    "1": {
      "id": "1",
      "$": "Project",
      "title": "test title",
      "description": "description",
      "contributors": [
        "2"
      ],
      "creatorProfileId": "3",
      "state": "INCOMPLETE"
    },
    "__where__": {
      "id == 1": {
        "1": {
          "id": "1",
          "$": "Project",
          "title": "test title",
          "description": "description",
          "contributors": [
            "2"
          ],
          "creatorProfileId": "3",
          "state": "INCOMPLETE"
        }
      }
    }
  },
  "tasks": {
    "1": {
      "id": "1",
      "$": "Task",
      "projectId": "123",
      "description": "test desc",
      "closeReason": "",
      "closeReasonDescription": "",
      "creatorProfileId": "123",
      "assigneeProfileId": "123",
      "state": "INCOMPLETE"
    }
  }
}
""";

create the mock #

  MockCloudFirestore mcf = MockCloudFirestore(source);

now you can #

main() {
  test("get a document", () async {
      MockCollectionReference col = mcf.collection("projects");
      MockDocumentReference docSnapshot = col.document("1");
      MockDocumentSnapshot docSnapshot = await doc.get();
      expect(docSnapshot.data["id"], "1");
      expect(docSnapshot.data["title"], "test project 1");
  });
}
main() {
  test("get snapshots", () async {
      MockCollectionReference col = mcf.collection("projects");
      Stream<QuerySnapshot> snapshots = col.snapshots();
      QuerySnapshot first = await snaphosts.first;
      expect(first, isNotNull);
      MockDocumentSnapshot docSnap = first.documents[0];
      expect(docSnap.data["id"], "1");
  });
}

To test widgets

create a backend to wrap firestore api #

class BackendApi {
  CollectionGet collectionGet;

  BackendApi(this.collectionGet);

  Future<Map<String, dynamic>> project() async {
    DocumentReference docRef = collectionGet("projects").document("1");
    DocumentSnapshot docSnap = await docRef.get();
    return docSnap.data;
  }
}

remove firestore dependency from widget #

class FirebaseDepWidget extends StatelessWidget {
  BackendApi backend;

  FirebaseDepWidget(this.backend);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: backend.project(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (!snapshot.hasData) {
          return Text("Loading...");
        }
        return Text("${snapshot.data["title"]}");
      },
    );
  }
}

now you can mock out firestore #

void main() {
  MockCloudFirestore mcf = getMockCloudFirestore();

  //BackendApi realBackend = BackendApi(Firestore.instance.collection);
  BackendApi mockBackend = BackendApi(mcf.collection);

  testWidgets('check task info ', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Container(
          child: FirebaseDepWidget(mockBackend),
        ),
      ),
    );
    await tester.pump(Duration.zero); // Duration.zero is required or you get a timer exception
    expect(find.text("test project 1"), findsOneWidget);
  });
}

using where on collection #

add expected results to collection node with __where__ key.See example on projects collection.

condition format #

field name operator expected value

condition operators (in order) #

  • isEqualTo: ==
  • isLessThen: <
  • isLessThanOrEqualTo: =<
  • isGreaterThen: >
  • isGreaterThanOrEqualTo: =>
  • arrayContains: 'array-contains'
  • isNull: null

about condition order #

dart does't give order guarantee to named arguments, so order is hard coded with in code. See operators for the order. Don't expect logical conditions like id > 1 & id < 5 this is not valid because of ordering, it must be like id < 5 & id > 1

examples #

  • id == 1
  • id < 5 & id > 1multiple conditions concat with &, spaces are required
  • id array-contains ["1", "2"] value should be json encoded
4
likes
80
pub points
63%
popularity

Easier way to mock cloud_firestore, without using `Firestore.channel.setMockMethodCallHandler`

Repository (GitHub)
View/report issues

Documentation

API reference

Uploader

ozan.turksever@gmail.com

License

Apache 2.0 (LICENSE)

Dependencies

cloud_firestore, flutter, mockito

More

Packages that depend on mock_cloud_firestore