Search code examples
flutterdartunit-testingsingleton

how to reset final singleton object in flutter test?


I'm facing an issue with resetting a singleton object in a Flutter test.

I have the following limitations that need to be taken into consideration while solving the problem:

1- The _singleton variable must remain final.

2- I cannot define a static or public method to change the value of _lock due to reduced security rules.

3- I must solve the problem within the flutter_test package and not any other package like mockito.

Here's the minimal code for the Singleton class :

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  bool _lock = false;

  Singleton._internal();

  factory Singleton() {
    assert(!_singleton._lock, "Singleton class has already been instantiated.");
    _singleton._lock = true;

    return _singleton;
  }

  static Singleton get instance => _singleton;
}

And here's the test that I'm trying to fix:

void main() {
  group('Singleton', () {
    test('should return the same instance', () {
      final instance1 = Singleton.instance;
      final instance2 = Singleton.instance;
      expect(instance1, same(instance2));
    });

    test('should throw an error when instantiated twice', () {
      Singleton(); // first instantiation
      expect(() => Singleton(), throwsA(isA<AssertionError>()));
    });

    test('should rest singleton and test pass', () {
      Singleton();
      expect(() => Singleton(), throwsA(isA<AssertionError>()));
    });
  });
}

My question is: How can I reset the Singleton object in the should reset the singleton and pass the test test while still adhering to the above limitations? .


Solution

  • I'm pleased to report that I've successfully resolved my issue.

    I was able to devise a solution by creating a public method that detects the current test environment.In this case, except in the object test mode, it will not be able to be reset .

    add below code to singleton class:

      void resetObject() {
        if (kIsWeb == false && Platform.environment.containsKey('FLUTTER_TEST')) {
          print("TEST MODE");
          _singleton._lock = false;
        }
      }
    

    set changes in test code:

        test('should rest singleton and test pass', () {
    
           Singleton.instance.resetObject();  //add this line here
    
          Singleton();
          expect(() => Singleton(), throwsA(isA<AssertionError>()));
        });
    
    

    If code is being run in a web environment, the program will continue to execute without encountering any errors.