How to create a state-based test for a method that calls other methods within the same class?

StackOverflow https://stackoverflow.com/questions/1519882

  •  19-09-2019
  •  | 
  •  

Question

I have the following code (which I've dumbed down for the question):

    public void HandleModeInit(int appMode){
        switch(appMode){
            Case 1:
                DoThis();
            Case 2:
                DoThat();
            Case 3:
                //no mode 3
            Case 4:
                DoSomethingElse();
            Case else:
                //do nothing
        }
    }

How would you unit test this method without turning it into an integration test (where you end up testing what DoThis(), DoThat(), and DoSomethingElse() are doing)? Since these method calls are made to methods within the same class as HandleModeInit(), how would you test this?

Although ideally, the method calls would be extracted out into another class, what if this move doesn't make any sense?

Was it helpful?

Solution

If you have control over what is passed into this method then I would pass in an interface that takes appmode as an argument which is an AppModeImplementationFactory. The purpose of this factory is to create AppModeImplementations. The factory would look as follows:

public class AppModeImplementationFactory: IAppModeFactory
{
   public IAppModeImplementation Create(int appMode)
   {
      // switch case goes here to create the appropriate instance
   }
}

When you pass in the factory this can be a mocked instance and you can verify that the create method is called. If you want to verify the instance type that is returned you would need to do that under a different test. This approach will fulfill your need of executing logic because of the app mode because the factory will return the implementation that you need based on the appMode.

Hope this helps

OTHER TIPS

Instead of using a switch/case statement to switch appModes, you can create an interface called IAppMode (I'll assume that the caller could decide which object to instanciate that properly implements IAppMode since they're already passing in an int to represent the App Mode).

Your caller would pass in an IAppMode object, then your method could call the DoThis() method of IAppMode.

You could then create a dummy object that implements IAppMode and inject it in to the method during testing.

It makes your code easer (using design patterns can do that) and test-able.

I realize (especially with you noting it) that the code is dumbed down, but if you do not test what the called methods do in this case, what are you actually testing? The value of appMode?

How exactly to attack this is hard (if not impossible) to say without knowing some about what is happening inside the called methods. Are they making any outbound calls (to external services, database, whatever) that can be mocked? If so, that may be a path forward. If they contain only behaviour that is encapsulated in the class, perhaps they alter some property value that you can check when the call to HandleModeInit returns?

I am typically not a fan of altering the design of my code for the sole purpose of making it more testable, but one approach would be to separate the public interface of your class from the internals, and then defining the internal interface as, well, an interface. That way you open up for mocking the internals.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top