Good day, I am trying to perform some unit testing on the below function that creates a document in Cloud Firestore. I have used a function in my app and it creates a document, but I want to write a test.dart file that performs unit testing for the below function and prints some output even on the console for verifications.
I think I am not writing my Test.dart in the proper way. I get an error.
Future<dynamic> createDoc(dataMap,collection) async {
final TransactionHandler createTransaction = (Transaction tx) async {
final DocumentSnapshot ds = await tx.get(db.collection(collection).document());
final Map<String, dynamic> result = {};
result.addAll(dataMap);
result['id'] = ds.documentID;
await tx.set(ds.reference, result);
return result;
};
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:test/test.dart';
import '../lib/service/createfirebase.dart';
void main() {
CreateFirebase cf = new CreateFirebase();
//test
test('Creating doc on firestore ', () async{
Object dataObj ={'name':'Dev','title':'Dev'};
var create = await cf.createDoc(dataObj, 'crude');
expect(true,create);
print('The doc details are');
print(dataObj);
});
}
The error after running this test is MissingPluginException(No implementation found for method Firestore#runTransaction on channel plugins.flutter.io/cloud_firestore)
But I do not understand why since I have all the dependencies and if I call that function in another class the doc gets created. But calling inside this test gives the above error. I guess I am not doing it in the right way.
Any contribution or any reference I can look at that can help on testing such functions?
TLDR: mazei513's comment is right. As Flutter Firestore is a plugin and not a package, it needs a platform to run on. This platform could be an iOS phone or an Android virtual device for instance. Therefore, you can't write a unit test to test a Firestore command. You have to use the integration_test package to execute this kind of tests.
As stated by the doc, a plugin
is a special kind of package that makes platform functionality available to the app. Plugin packages can be written for Android (using Kotlin or Java), iOS (using Swift or Objective-C), web, macOS, Windows, Linux, or any combination thereof.
If you take a look at the Firestore plugin in /usr/local/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.7.0
, you'll see:
jjanvier:nouba$ ls -l /usr/local/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-1.7.0
total 48
drwxr-xr-x 4 jjanvier jjanvier 4096 Oct 6 17:20 android
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 ios
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 lib
drwxr-xr-x 3 jjanvier jjanvier 4096 Oct 6 17:20 macos
-rw-r--r-- 1 jjanvier jjanvier 912 Oct 6 17:20 pubspec.yaml
As Firebase plugins actually run native code depending on the platform (Android, iOS, MacOS...), they need a "real" device to run on. Therefore, it doesn't work with flutter test
that is nothing but a simple Dart executor.
To get a platform your tests can run on, you have several options. For instance:
Follow this documentation to configure integration_test
for your project. Don't forget to use testWidgets
instead of test
as this what will allow to launch your tests in the device emulator instead of in the Dart simple environment.
Once done, all the integration/end to end tests can be launched with flutter test integration_test
.
If you launch the command flutter test integration_test
as is, there is a high chance the document {'name':'Dev','title':'Dev'}
present in your test will appear in your production database.
To counteract this problem, you have mainly 2 options at your disposal:
For my project, I chose the second option. With a single command, you can boot the Firebase emulator, loads fixtures and run the tests :
firebase --config="firebase.test.json" emulators:exec --import fixtures/ "flutter test integration_test/ --dart-define=FOO=bar"
Let's detail the command:
--config="firebase.test.json"
launch firebase with this config file. This allows me to keep my local emulator suite running while I launch the tests--import fixtures/
: loads the folder "fixtures" as datasetemulators:exec "flutter test integration_test/ --dart-define=FOO=bar"
: launch the integration tests with a FOO env varI didn't suggest you to mock or fake Firestore as it makes no sense in your case. There is no point in using a double for Firestore if what you want to test is that you can actually write properly in Firestore.
But, in some cases it can be useful. For instance to unit test a business behavior that at some point writes or queries Firestore.
Again, you have several solutions:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With