Flutter中如何模拟Firebase实时数据库(非Firestore)?
Hey there! I get it—working with both Firestore and Firebase Realtime Database, having a smooth testing flow with cloud_firestore_mocks but hitting a wall with RTDB can be super frustrating. Let me walk through the options you had back then, plus note your final solution:
Option 1: Roll Your Own Mock Classes
Since there’s no official or widely adopted mock package for RTDB like there is for Firestore, you can manually build mock versions of FirebaseDatabase, DatabaseReference, and related classes to simulate local data storage and operations. Here’s a quick example to get you started:
class MockDatabaseReference implements DatabaseReference { final Map<String, dynamic> _localData = {}; String? _currentNodePath; @override DatabaseReference child(String path) { _currentNodePath = path; return this; } @override Future<void> setValue(dynamic value) async { if (_currentNodePath != null) { _localData[_currentNodePath!] = value; } // Add optional logic like simulated error throws if needed } @override Future<DataSnapshot> once() async { return MockDataSnapshot(_localData[_currentNodePath!]); } // Implement other methods you use (update, remove, etc.) as required // For unused methods, return default values like empty futures } class MockDataSnapshot implements DataSnapshot { final dynamic _storedValue; MockDataSnapshot(this._storedValue); @override dynamic get value => _storedValue; // Fill in other required properties/methods with defaults } class MockFirebaseDatabase implements FirebaseDatabase { @override DatabaseReference reference() => MockDatabaseReference(); // Add other FirebaseDatabase methods you use if necessary }
With this setup, you can create a MockFirebaseDatabase instance in tests, write data to it, and verify that the local storage matches your expected results—just like you did with the Firestore mock.
Option 2: Use Mockito to Generate Mocks
If writing manual mock classes feels tedious, the mockito package can auto-generate them for you. Here’s how to set that up:
- Add the required dev dependencies to your
pubspec.yaml:
dev_dependencies: mockito: ^5.4.0 build_runner: ^2.4.4
- Create a file (e.g.,
rtdb_mocks.dart) to define your mock templates:
import 'package:firebase_database/firebase_database.dart'; import 'package:mockito/mockito.dart'; class MockFirebaseDatabase extends Mock implements FirebaseDatabase {} class MockDatabaseReference extends Mock implements DatabaseReference {} class MockDataSnapshot extends Mock implements DataSnapshot {}
- Run the build command to generate the actual mock code:
flutter pub run build_runner build
Then in your tests, you can mock interactions and verify method calls:
void main() { late MockFirebaseDatabase mockRtdb; late MockDatabaseReference mockRef; setUp(() { mockRtdb = MockFirebaseDatabase(); mockRef = MockDatabaseReference(); // Stub core methods to return our mock reference when(mockRtdb.reference()).thenReturn(mockRef); when(mockRef.child("this_node")).thenReturn(mockRef); }); test('Verify setValue is called with correct data', () async { const testObject = {"username": "kobowo", "score": 100}; await mockRef.setValue(testObject); // Confirm setValue was invoked exactly once with our test data verify(mockRef.setValue(testObject)).called(1); }); }
This is perfect if you just need to validate method invocations, though you’ll need to add extra logic if you want to simulate actual data persistence.
Your Final Solution: Migrating to Firestore
I totally get why you decided to migrate all data to Firestore—having a unified database with mature testing tooling is a huge win for long-term maintainability. Firestore’s mock ecosystem is robust, and you’ll only have one set of testing logic to keep up with moving forward.
内容的提问来源于stack exchange,提问作者kobowo

