Unit Testing Private Functions in Junit With Mockito

Testing Private method using mockito

You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.

How to stub private methods of class under test by Mockito

This could be achieved by PowerMockito framework.

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {

private SomeClass someInstance;

@Before
public void setUp() throws Exception {

someInstance = PowerMockito.spy(new SomeClass());
}

@Test
public void sendRequest() throws Exception {

String json = "JSON";
String text = "Some text";
int messageId = 1;

PowerMockito.doReturn(true).when(someInstance, "isMethod");
PowerMockito.doReturn(messageId).when(someInstance, "getMessageId", json);

someInstance.sendRequest(json, text);

PowerMockito.verifyPrivate(someInstance).invoke("isMethod");
PowerMockito.verifyPrivate(someInstance).invoke("getMessageId", json);
PowerMockito.verifyPrivate(someInstance).invoke("sendMessage", messageId, text);
}

}

How do I test a class that has private methods, fields or inner classes?

If you have somewhat of a legacy Java application, and you're not allowed to change the visibility of your methods, the best way to test private methods is to use reflection.

Internally we're using helpers to get/set private and private static variables as well as invoke private and private static methods. The following patterns will let you do pretty much anything related to the private methods and fields. Of course, you can't change private static final variables through reflection.

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

And for fields:

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);


Notes:

  1. TargetClass.getDeclaredMethod(methodName, argClasses) lets you look into private methods. The same thing applies for
    getDeclaredField.
  2. The setAccessible(true) is required to play around with privates.

Verifying no argument and private methods using Mockito

You could mock scheduleList and orderList instead and use verify to make sure the correct methods are being called from them.

public class MyRuleTest
{
private MyRule myRule;
private ScheduleList scheduleListMock;
private OrderList orderListMock;

@Before
public void setUp() throws Exception
{
scheduleListMock = mock(ScheduleList.class);
orderListMock = mock(OrderList.class);

myRule = new MyRule(orderListMock, scheduleListMock);
}

@Test
public void testExecute()
{
myRule.execute();
verify(scheduleListMock).foo();
verify(orderListMock).bar();
}

...

You would just replace foo and bar with whatever methods you are expecting to be called.

If you are testing MyRule, you shouldn't be mocking it. A good rule of thumb is to not mock the class that is under test.



Related Topics



Leave a reply



Submit