'How to unit test this method that uses private member?

bool get animationCompleted => 
_popupAnimationSubject.value == PopupAnimationStatus.completed;

I have this method in my PopupController class where _popupAnimationSubject is a BehaviorSubject so I can't expose as a public member and I can't put it in the constructor as a parameter since the user is not supposed to provide its value but it is rather created internally.

I am struggling to test this method. There is this answer that suggests to make it public and annotate it for testing only but as I said this is an api and I don't want non-careful users to break the state of the controller unintentionally.

What is the best way to test this method?

note: I also looked at this and this but they didn't answer me as this is not a "getter" despite the name because it contains some logic (the equality check)



Solution 1:[1]

As @jamesdlin commented here and answered there, a way to solve this is to separate the class into an interface and an implementation.

Although this class can have only one implementation in my case but this will work as now I can define an interface (notice how the subject i.e. the dependency that was needed in the test is now injected into the implementation via the constructor so now in the tests I can actually test the implementation and inject it with mocked dependencies, and for the users of the api, the interface and the factory constructor below will hide all of this from them):

abstract class PopupController {
  factory PopupController() => PopupControllerImpl( popupAnimationSubject: ...);
   //... 
}

and in the test:

 test('animationCompleted getter returns correct value.', () {
        // create the mocks
        MockBehaviorSubject mockSubject = MockBehaviorSubject();
        // configure the mocks
        when(mockSubject.value).thenReturn(...);
        // create the real objects
        PopupControllerImpl controllerImpl = PopupControllerImpl(popupAnimationSubject: mockSubject);
        expect(
            controllerImpl.animationCompleted, true);
      });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1