Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ozanturksever/mock_cloud_firestore

Mock Cloud Firestore
https://github.com/ozanturksever/mock_cloud_firestore

cloud-firestore dart firebase firestore flutter mock testing

Last synced: 21 days ago
JSON representation

Mock Cloud Firestore

Awesome Lists containing this project

README

        

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

```dart
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

```dart
MockCloudFirestore mcf = MockCloudFirestore(source);
```

## now you can

```dart
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");
});
}
```

```dart
main() {
test("get snapshots", () async {
MockCollectionReference col = mcf.collection("projects");
Stream 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
```dart
class BackendApi {
CollectionGet collectionGet;

BackendApi(this.collectionGet);

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

## remove firestore dependency from widget

```dart
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

```dart
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 > 1`multiple conditions concat with ` & `, spaces are required
- `id array-contains ["1", "2"]` value should be json encoded