Search code examples
unit-testingmockingmockitoprivatepowermock

Yet Another Unit Testing Issue


I want to unit test a class with about a billion dependencies. In this specific case, I want to test a method that looks a bit like this:

class Suicide
{
  IrrelevantObject n;
  ObjectsThatGetInitializedWhoTheFKnowsWhere m;

  private String privateFunc()
  {
     //... tons of things with dependencies
     // I am not testing this in this test.. or should I?
  } 

  public String testFunc()
  {
     String x = "";
     String y = privateFunc();
     if(n.anotherPrivateFunc(y) == 5) 
           x = "yolo";
     return x;
  } 
}

Alright so here is the question: I have read that you should NOT mock PRIVATE methods, but in this case, because of their endless dependencies, I desperately want to stub them just so I can test that the method works. If I am supposed to stub information in the private method, I can see how that makes sense too, but I just have no clue how to do that with Mockito or any other framework. Thanks a ton for the help.


Solution

  • You could simplify those dependencies. For example, replace them by interfaces.

    class Suicide
    {
      IIrrelevantObject n;
      IObjectsThatGetInitializedWhoTheFKnowsWhere m;
    

    If those interfaces don't exist, create them!

    Then you just have to let your test inject mock of those interfaces. There are several ways you can do this:

    • Add setter (potentially call them setForTest so that it's a clear smell if prod code uses it)
    • Make them protected and inherit this class in a test
    • Add a constructor which can take those interfaces, and use this one in your test

    Now, you're in the case of a class with lot of dependencies, but dependencies you can easily mock. So you don't particularly need to mock the private anymore.


    On the other hand, you might want to consider end-to-end test. ie : call the main and let the code run as it would in prod (possibly in a sandbox).

    • Advantage: you don't have to worry about dependencies / private anymore, since you're at a higher level
    • Drawback: according to your infrastructure, it might not always be simple to put in place such tests. (And those tests are in general slower than unit tests)

    Anyway, both approaches aren't incompatible