In my production code I set environment variables using the --DART-DEFINE
flag and then retrieve them by using String.fromEnvironment
.
How can I override the value returned by String.fromEnvironment
in my unit tests, to test how my production code responds to different environment variable values?
CodePudding user response:
The flutter test
command supports --dart-define=NAME=VALUE
, but this is annoying to automate. It's also not possible to change dart defines at runtime.
What my team does is declare all of the dart defines in a single file, and use separate global variables to override them during tests:
String? fooDefineOverride;
String get fooDefine => fooDefineOverride ?? const String.fromEnvironment('foo');
void resetOverrides() {
fooDefineOverride = null;
}
void main() {
setUpAll(() {
resetOverrides();
});
test('Foo is foobar', () {
fooDefineOverride = 'foobar';
// ... do tests
});
}
CodePudding user response:
Wrap your environment variables in a class and use your preferred dependency injection or service locator package (eg. get_it) to access your injected class from within your app.
Your environment_config.dart
:
class EnvironmentConfig {
final String someValue;
EnvironmentConfig({
required this.someValue,
});
factory EnvironmentConfig.init() {
const someValue = String.fromEnvironment('someEnvVar');
return EnvironmentConfig(someValue: someValue);
}
}
main.dart
void main() {
// instance can now be accessed from any class/widget within your app
GetIt.I.registerSingleton<EnvironmentConfig>(EnvironmentConfig.init());
runApp(MyApp());
}
Then within unit tests, you can inject your own instance of EnvironmentConfig
with your own values:
void main() {
setUp(() {
final config = EnvironmentConfig(someValue: 'myCustomValue');
GetIt.I.registerSingleton<EnvironmentConfig>(config);
});
tearDown(() {
GetIt.I.reset();
});
test('Verify env vars', () {
expect(GetIt.I<EnvironmentConfig>().someValue, equals('myCustomValue');
});
}