Search code examples
flutterunit-testingdartenvironment-variables

Flutter override environment variables in unit tests


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?


Solution

  • 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');
        });
    }
    

    EDIT: Given this is now the top result when searching for an answer to this, it's worth noting that the trade-off to the above approach is that it doesn't cater for tree-shaking, as the EnvironmentConfig class is not a compile-time constant when using the factory constructor.