Search code examples
javajunitmockitopowermockpowermockito

Setting private field in abstract super class using mockito


I am having a abstract super class TP and which have a concrete sub class ETP. This is my code:

    abstract class TP {

    private Configuration app;        
         protected MC bMC() {    
         }
    }

and sub class ETP code is:

 public class ETP extends TP {        
    private Configuration app;       
       public MC pT() {
          bMC();
       }
   }

I am writing test case for ETP which is ETPTest which looks like this

public class ETPTest {       
 @Before
    public void setUp() throws Exception {
       // as TP is abstract i am initializing with ETP
          TP = new ETP();        
       // some initialization
   }    
    Whitebox.setInternalState(TP, app);
}

but app is getting passed as null in TP and getting NPE in TP.

any ideas or suggestions?

app is a private variable defined in both TP and ETP; and I am trying to set internal state for app which is in TP.


Solution

  • Your difficulties to such things can be seen as a symptom.

    You can decide that the cure is to spent hours until you get the mocking parts to circumvent around that problem.

    Whereas the other option is: understand that the given design is deficient:

    • sub classes should absolutely not care about private fields in super classes. The whole point of private is to make things an "implementation detail" that no other class should know or care about
    • Worse: by putting up a second private field with the same name, you just added to that confusion. Those will be to different private fields; there is no "overriding" or "polymorphism" here.

    In the end, you probably do not understand how to properly design a solution that uses inheritance and abstract base classes. You should thus step back, and think for example, if a solution like this helps:

    public abstract class Base {
      protected abstract Configuration getConfiguration();
    
      public final void doSomething() {
        ... calls getConfiguration() to do its jobs
      }
    }
    

    and then:

    public abstract class Subclass extends Base {
      protected Configuration getConfiguration() {
        return whatever
    

    As a rule of thumb: clean, straight-forward, non-surprising designs can most often be unit tested simply by using dependency injection and one mock here and another one there. As soon as you have to look into all these complex "solutions"; such as mocking super-class methods/fields; or mocking static methods, ... you are already suffering from a bad design; and instead of fixing that problem; you try to work around it.

    That will not help you in the long run. Because the real problem is the "smelly" design in your production code.