搜索插件、代码仓与 APP 分类

插件详情v4.5.0

fake_cloud_firestore

以前称为 cloud_firestore_mocks。Cloud Firestore 的模拟实现。使用此包来对使用 Cloud Firestore 的应用进行单元测试。

AndroidiOSWebmacOSWindows
近 30 天下载
30.7万
喜欢数
147
Pub 分数
150

安装插件

flutter pub add fake_cloud_firestore

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

一个用于单元测试 Flutter 应用程序的 Cloud Firestore 虚拟实现。它模拟了真实 Cloud Firestore 服务的行为,使开发者能够在无需实际 Firebase 后端的情况下测试应用程序的数据逻辑。该包非常适合隔离测试,并在开发过程中确保结果的一致性和可重复性。最初名为 cloud_firestore_mocks,支持所有主要平台,包括 Android、iOS、Web、macOS 和 Windows。

适合场景

  • 单元测试依赖 Firestore 的逻辑
  • 在没有实时 Firebase 连接的情况下测试应用状态
  • 在集成测试期间隔离组件
  • 在测试中模拟不同的 Firestore 响应
  • 部署前验证数据处理

主要特点

  • 与 Cloud Firestore API 完全兼容
  • 支持所有主要的Flutter平台
  • 测试环境的简易设置
  • 模拟的文档和集合操作
  • 无需 Firebase 项目配置

适合对象

  • Flutter 开发人员编写单元测试
  • 优先考虑测试可靠性的团队
  • 具有复杂 Firestore 交互的项目
  • 开发人员在测试中避免真实的 Firebase 成本
  • 需要确定性测试结果的应用程序

使用建议

  • 不适用于端到端测试
  • 不复制实时同步行为
  • 仅限测试客户端逻辑
  • 需要手动设置初始数据
  • 可能无法反映真实 Firestore 的所有边缘情况

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

Fake Cloud Firestore

pub package Unit Tests Buy Me A Coffee

Fakes to write unit tests for Cloud Firestore. Instantiate a FakeFirebaseFirestore, then pass it around your project as if it were a FirebaseFirestore. This Fake acts like Firestore except that will only keep the data in memory. To help debug, you can use FakeFirebaseFirestore.dump() to see what's in the fake database. This is useful to set up the state of your database, then check that your UI behaves the way you expect.

This project works well with firebase_auth_mocks. If you use them together, you can even test your app with security rules. See below.

Usage

Simple example
import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';

void main() {
  final instance = FakeFirebaseFirestore();
  await instance.collection('users').add({
    'username': 'Bob',
  });
  final snapshot = await instance.collection('users').get();
  print(snapshot.docs.length); // 1
  print(snapshot.docs.first.get('username')); // 'Bob'
  print(instance.dump());
}

// Prints out:
// {
//   "users": {
//     "z": {
//       "name": "Bob"
//     }
//   }
// }

See more examples at fake_cloud_firestore/test/fake_cloud_firestore_test.dart.

In a UI test
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
import 'package:firestore_example/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

const MessagesCollection = 'messages';

void main() {
  testWidgets('shows messages', (WidgetTester tester) async {
    // Populate the fake database.
    final firestore = FakeFirebaseFirestore();
    await firestore.collection(MessagesCollection).add({
      'message': 'Hello world!',
      'created_at': FieldValue.serverTimestamp(),
    });

    // Render the widget.
    await tester.pumpWidget(MaterialApp(
        title: 'Firestore Example', home: MyHomePage(firestore: firestore)));
    // Let the snapshots stream fire a snapshot.
    await tester.idle();
    // Re-render.
    await tester.pump();
    // // Verify the output.
    expect(find.text('Hello world!'), findsOneWidget);
    expect(find.text('Message 1 of 1'), findsOneWidget);
  });
}

See more examples at fake_cloud_firestore/example/test/widget_test.dart.

Exceptions
Based on the state

Most features automatically throw exceptions depending on the state, so you do not need to mock them. For example, calling DocumentSnapshot.get on a missing field will throw a StateError.

final firestore = FakeFirebaseFirestore();
final collection = firestore.collection('test');
final doc = collection.doc('test');
await doc.set({
  'nested': {'field': 3}
});

final snapshot = await doc.get();

expect(() => snapshot.get('foo'), throwsA(isA<StateError>()));
expect(() => snapshot.get('nested.foo'), throwsA(isA<StateError>()));
Mocking exceptions

Furthermore, some methods allow mocking exceptions manually, for example to simulate network errors. You can even set conditions on the parameters using the standard Dart matchers. Here are the methods which support mocking exceptions:

  • DocumentReference.get, set, update, delete.
  • Query.get.
final instance = FakeFirebaseFirestore();
final doc = instance.collection('users').doc(uid);
whenCalling(Invocation.method(#set, null))
    .on(doc)
    .thenThrow(FirebaseException(plugin: 'firestore'));
expect(() => doc.set({'name': 'Bob'}), throwsA(isA<FirebaseException>()));

For examples of how to set conditions on when to throw an exception, see firebase_auth_mocks#throwing-exceptions.

Security Rules

You can pass the security rules that you use in production in Firestore to [FakeFirebaseFirestore]. When operating on [DocumentReference] using get, set, update, or delete, [FakeFirebaseFirestore] will then check security rules and throw exceptions if access is restricted. In the example below, we restrict users/{userId} documents to their respective owners. Before they sign in, they cannot access any document inside the users collection. Once they sign in, they have access to only their own users/[uid] document.

import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
import 'package:firebase_auth_mocks/firebase_auth_mocks.dart';
import 'package:test/test.dart';

// https://firebase.google.com/docs/rules/rules-and-auth#leverage_user_information_in_rules
final authUidDescription = '''
service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}''';

main() async {
  test('security rules' {
    final auth = MockFirebaseAuth();
    final firestore = FakeFirebaseFirestore(
        // Pass security rules to restrict `/users/{user}` documents.
        securityRules: authUidDescription,
        // Make MockFirebaseAuth inform FakeFirebaseFirestore of sign-in
        // changes.
        authObject: auth.authForFakeFirestore);
    // The user signs-in. FakeFirebaseFirestore knows about it thanks to
    // `authObject`.
    await auth.signInWithCustomToken('some token');
    final uid = auth.currentUser!.uid;
    // Now the user can access their user-specific document.
    expect(
        () => firestore.doc('users/$uid').set({'name': 'abc'}), returnsNormally);
    // But not anyone else's.
    expect(() => firestore.doc('users/abcdef').set({'name': 'abc'}),
        throwsException);
  });
}

See https://github.com/atn832/fake_cloud_firestore/blob/master/test/security_test.dart for more examples of security rules.

Right now we only support operations on DocumentReference. Later we will implement security checks for batch requests, collections and queries. Furthermore, we do not support timestamps and durations yet. See Fake Firebase Rules for an exhaustive list of what is and is not supported.

Resetting security rules

You can also dynamically change the security rules. This is useful if you want to first set up data without any restriction, then apply security rules for the actual tests.

https://github.com/atn832/fake_cloud_firestore/blob/0bd0b648241c0ed3e6eac2c26eef85135e3e47f9/test/security_test.dart#L82-L85

Features

  • Dump the state of the fake firebase with FakeFirebaseFirestore.dump().
  • Clear the fake firebase with FakeFirebaseFirestore.clearPersistence().
  • Create documents and collections.
  • Supports Converters.
  • Create documents with collection.add or document.set.
  • Batch writes and runTransaction.
  • Query documents with collection.snapshots or query.get.
  • Queries:
    • Filter results with query.where. The library supports equals, isGreaterThan, isGreaterThanOrEqualTo, isLessThan,isLessThanOrEqualTo, isNull, isNotEqualTo, arrayContains, arrayContainsAny, whereIn and whereNotIn.
    • Supports filtering by special fields like FieldPath.documentId and __name__.
    • Sort results with query.orderBy.
    • Limit results with query.limit, limitToLast, startAfterDocument, startAt, startAtDocument, endAt, endAtDocument, endBefore, endBeforeDocument. Note: startAnd and endAt work only on exact matches.
    • Filter with Filter, including composite filters like Filter.and and Filter.or.
    • Aggregate with query.count, query.aggregate(sum(field1), average(field2)...).
  • ValueField:
    • set timestamps with FieldValue.serverTimestamp(). Optionally you can pass a Clock when instantiating FakeFirebaseFirestore to define what time gets set.
    • delete values with FieldValue.delete().
    • update numerical values with FieldValue.increment.
    • update arrays with FieldValue.arrayUnion and FieldValue.arrayRemove.
  • Mock exceptions for DocumentReference.set.
  • Security rules:
    • Initialize FakeFirebaseFirestore with custom security rules.
    • FakeFirebaseFirestore takes authentication state from firebase_auth_mocks into account.
    • Reset security rules.
    • DocumentReference.get, set, update and delete are protected.

Compatibility table

cloud_firestore fake_cloud_firestore
6.7.1 4.2.0
6.2.0 4.1.0
6.0.0 4.0.0
5.0.0 3.0.0
4.17.0 2.5.0
4.4.0 2.4.0
4.0.0 2.0.0
3.4.0 1.3.0
3.0.0 1.2.1
2.2.0 1.1.0
2.1.0 1.0.2
1.0.0 0.8.4
0.16.0 0.6.0
0.14.0 0.5.0
0.13.1+1 0.4.1
0.13.0+1 0.2.5
^0.12.9+6 0.2.0

Features and bugs

Please file feature requests and bugs at the issue tracker.

所属分类

依赖

依赖清单 10 项

源码仓库

使用此插件的项目