0
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)

Ken White
  • 123,280
  • 14
  • 225
  • 444
HII
  • 3,420
  • 1
  • 14
  • 35
  • Can you share more of your `PopupController`? – Guilherme Gabanelli Apr 26 '22 at 03:13
  • I've added [another answer](https://stackoverflow.com/a/72008212/) that maybe would be more palatable to you if it could apply to your situation. – jamesdlin Apr 26 '22 at 04:02
  • @jamesdlin that solved the problem., thanks. I wonder if this separation is normal (as there will only ever be just one implementation of this class) or should I rethink my design of this class – HII Apr 26 '22 at 11:23

1 Answers1

0

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);
      });
HII
  • 3,420
  • 1
  • 14
  • 35