Search code examples
javajunitmockitopowermockito

Mockito JUnit testing: check method call in constructor


I have a class Foo with private and public or protected methods. For example:

public class Foo{

   private int number;
   public Foo(){
      setup();
      doSthing();
   }

   private void doSthing(){
      number=10;
   }

   public void setup(){
   }

   protected int getNumber(){
      return number;
   }

   public void run(){
      getNumber();
      //Do blah blah...
    }    
}

And I am trying to test this class using Mockito.

public class FooTest
{
   public void testMethods()
   {
      Foo foo = PowerMockito.mock (Foo.class);

      //1 What should I do to see that setup() and doSthing()
      //has been called on Foo construction

      mock.run();
      //2 What should I do to see that getNumber()
      //has been called on run() method call
   }
}

I am also hoping to include "times(1)" if possible. I'd appreciate your help.


Solution

  • You are getting this wrong:

    First of all: please do not use any of the PowerMock... frameworks. They rely on byte code manipulation; and sooner or later that calls for trouble. Believe me, I have spent many hours hunting really strange errors for no good reasons.

    Then: do not test your code this way!

    You use a mocking framework to create/control those objects that you pass to your "class under test". You don't use the framework to directly test your "class under test"!

    You also don't want to write test code that knows about private methods - those are implementation details.

    What you do instead:

    a) as said, you can use mocking to pass objects into your class under test. And then you can control/verify those mocks see the calls that you expect your "class under test" to make

    b) you create objects of your "class under test" ... and then "assert" on the properties of those objects; or on results that method calls return.

    Just to be precise: a mocked object ... doesn't know anything about the code in the "original" class. It is a mock! You can't use it for the kind of testing that your question implies you want to do. Either you call methods on your real class; or you specify something for a mock. But creating a mock to then "associate" it to the concrete class implementation ... is simply impossible.

    Finally: if you think that your concrete class is actually "too big" to just be created the normal way for tests ... then chances are: your class is simply too big for anything else. Classes should be small; and their design should follow SOLID principles.

    Long story short: don't try to force un-testable code into "tests", by using PowerMock... You better invest some more time to improve the quality of your production code; that will result in much higher "return on investment".