java-james / flutter_dotenv

Loads environment variables from `.env`.
https://pub.dartlang.org/packages/flutter_dotenv
MIT License
209 stars 46 forks source link

DotEnv._getEntriesFromFile Instance of 'FileNotFoundError' in UnitTest of Flutter Package #39

Open Guo-Zhang opened 3 years ago

Guo-Zhang commented 3 years ago

I have followed the docs, but still get the error. I am wondering whether it is not available to use it in flutter packages?

ngxingyu commented 3 years ago

Perhaps you can take a look at the test/dotenv_test.dart file for a sample approach taken when testing this package (theres a testLoad method which takes in the content of the sample env file as a string to bypass the need to use the _getEntriesForFile method not sure if this was the best implementation but it works for testing). Alternatively you can mock the entire DotEnv class if you do not need to test the dotenv methods itself.

Guo-Zhang commented 3 years ago

Thanks so much! testLoad works.

I am new to Flutter and Dart, so I am confused that why this works. The difference between them is that the load function needs rootBundle which maybe not work in unittest environment.

I will use this package in two ways. In my local environment, I will use .env files that are ignored by git, and load them with this package. In my CI environment, I need to export env variables from CI environments. There are two different usages for this package. One is to load some common variables for the app, and the other is to load some variables for running the tests.

Therefore, I suggest to design the API in the following way: it is helpful to make local and cloud environment same, so they should share the same API. It is different to use them in the apps and packages/tests, so they can export different APIs for developers.

Maybe the API for APPs and for Packages/tests can be designed in different modules, so we can import like this:

In apps,

import "package:flutter_dotenv/flutter_dotenv.dart";

In tests,

import "package:flutter_dotenv/flutter_dotenv_test.dart";

In this way, developers can easily know that the second API are designed for testing.

We can consider the load and testLoad as different constructors for the class. The main difference is one with String and other with File object. In src/dotenv.dart, the API can be designed as this way. Than we give different default settings for exported APIs.

These above are the best way I can thinks of.

I am willing to discuss with you on API designs and their implements, and can pull request some code if needed. My team needs a good env variable package to support our apps, packages and plugins.

ngxingyu commented 3 years ago

I went to try it out, and i believe the .load method will not throw the FileNotFoundError if you add your test env file to your pubspec assets, and run TestWidgetsFlutterBinding.ensureInitialized(); before running .load in your test file.

The testLoad method just lets you populate the dotenv class from your .env files that you do not want to add to pubspec.yaml. I'm not sure if there's a use case for this other than testing if your .env file can be parsed by the dotenv package.

If you just want to populate the dotenv class with values to be used in other components for testing, I suppose mocking the dotenv class or using the mergeWith: {'Your variable':'value'} would be a viable alternative.

Guo-Zhang commented 3 years ago

I have set the .env file in the pubspec.yaml. I didn't run TestWidgetsFlutterBinding.ensureInitialized(); since it is not a Widget test but only some toolkits. I think this is the reason since rootBundle requires some settings for Flutter apps.

awasum commented 2 years ago

If you face this problem when running on Android Emulator, then make sure you are passing the right path in the main.dart file.. instead of just using the .env filename, use the full path like, assets/.env (assuming you have your .env file under assets/ directory) if your .env is not located in the root directory of the project.