Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing overloaded methods

I have a class with two public methods, which do very similar job, but differ in argument types. Those methods only extract needed data and both call the same private method which actually does the job.

My question is, what is the best way to test this class? I would like to test only public method, so to be sure both methods return correct data I end up creating two test methods for literary the same assertion/concept.

Also I don't know if moving assertions to private method to not to duplicate assertions' code is the best idea. Sometimes tests are important part of documentations and I would like to let other developers fully understand my code by reading the tests.

I use junit 4, mockito and I don't use TDD. Would have TDD helped me avoid this problem anyway?

Regards

like image 879
user1331072 Avatar asked Oct 26 '15 00:10

user1331072


1 Answers

First of all: TDD is not a magical bullet that will kill all your problems. It can help to make code better from the start, but you still can produce bad code even with TDD.

So, the first question you have to ask yourself is, if you actually need two methods. That's a question nobody can answer without any code.

If you actually need two methods, then both are part of your public api and should be tested. That way you can be sure that there's no error in your parameter mapping (would be embarassing, if your private method works great but you fail to give the correct parameters).

You can, of course, also test the private method directly, but honestly, I don't think that's a good way. Another possibility is that you can solve your problem by using composition, in other words, don't make it a private method but add an interface that can be set to do the work of the private method, for example, instead of...

public class MyPublicClass {
   public void method1(Data1 x) {
       ....call private method
   }

   public void method2(Data2 x) {
       ....call private method
   }

   private void methodX(String, int, int, double, String)
       ...do the work
   }
}

...you could do...

public class MyPublicClass {

   private MyNewInterface executor;

   // probably good idea to make executor final and set it in the constructor

   public void method1(Data1 x) {
           executor.method( ... );
   }

   public void method2(Data2 x) {
           executor.method( ... );
   }
}

This way you can test multiple things idependently:

  • Do the public methods give the correct parameters (by using a MyNewInterface of your interface which you can verify then)?
  • Does your implementing class do the work correctly (which you then only need to test once)?

Only you can answer the question if such a refactoring is a good idea for your case.

like image 70
Florian Schaetz Avatar answered Sep 25 '22 13:09

Florian Schaetz