简体   繁体   中英

Mocking constructor using PowerMockito doesn't work

I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.

public class MyClass{

   private MyObj obj;

   MyClass (String profile)
   {
      //some 3rd party library call
      obj = thridPartyLib.someMethod(profile);       
   }

   public String someMethod(){
     return obj.someExternalCall();
   }

}

Class which I want to test

public class ClassTobeTested{

   public void execute(){
       //some code
       // ......
       MyClass myClass = new MyClass(profile);
       myclass.someMethod();
   }
}

What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.

 @RunWith(PowerMockRunner.class)
 @PrepareForTest(MyClass.class)
 public class ClassTobeTestedTest {

     private MyClass mockMyClass;
     private ClassTobeTested classUnderTest;


    @Before
    public void init() {    
       classUnderTest = new ClassTobeTested();
       mockMyClass = PowerMockito.mock(MyClass.class);  
    }

   @Test
   public void testExecute(){

      PowerMockito.whenNew(MyClass.class)
                 .withArguments(Mockito.any())
                 .thenReturn(mockMyClass);

      classUnderTest.execute();     
  }
}

Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work

@RunWith(PowerMockRunner.class)
@PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {

  private MyClass mockMyClass;
  private ClassTobeTested classUnderTest;


  @Before
  public void init() {
    classUnderTest = spy(new ClassTobeTested());
    mockMyClass = PowerMockito.mock(MyClass.class);
  }

  @Test
  public void testExecute() throws Exception {

    PowerMockito.whenNew(MyClass.class)
        .withArguments(Mockito.any())
        .thenReturn(mockMyClass);

    classUnderTest.execute();
  }
}

The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj . For example:

class MyObjFactory {
   MyObj create(String profile) {
       return new MyClass(profile);
  }
}

then

public class ClassTobeTested {
    private final MyObjFactory factory;

    public  ClassTobeTested(MyObjFactory factory) {
        this.factory = factory;
    }

   public void execute(){
       //some code
       // ......
      // MyClass myClass = new MyClass(profile);
      MyClass myClass = factory.create(profile);
      myclass.someMethod();
   }
}

so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM