Mocking private methods used in public method with PowerMock, Mockito, and TestNG
Solution 1
I don't think this is a problem with PowerMock. It looks like it should work just fine as is. I wonder if there is a problem with TestNG interacting with PowerMock?
I have no experience with TestNG, so I tried running the class in JUnit. SomeClass
was left as is, SomeClassTest
was minimally modified to use JUnit:
import static org.powermock.api.mockito.PowerMockito.*;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {
@Test
public void testSomePublicMethod() throws Exception {
final int num = 4;
final SomeClass someClassSpy = spy(new SomeClass());
doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
doReturn(12).when(someClassSpy, "somePrivateMethod2", num);
final int result = someClassSpy.somePublicMethod(num);
Assert.assertEquals(result, 20);
}
}
The test passes.
Do you need to specify a PowerMockRunner.class
using @RunWIth
or some similar annotation, as with JUnit? If I remove that annotation I recieve the same error message you posted.
EDIT:
According to this link: http://code.google.com/p/powermock/wiki/TestNG_usage
You need to tell TestNG to use the PowerMock object factory. To do this programmatically, add a method like this to your test class:
@ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
or to be on the safe side you can also extend from the PowerMockTestCase:
@PrepareForTest(SomeClass.class)
public class SomeClassTest extends PowerMockTestCase {
//...
}
Solution 2
You can't do by that way. Did you try to use reflection?
By using reflection, you can mock the private methods by mocking the invoke methods, or simpler: you can change it to public temporary, then after the test (maybe in the tearDown) - you can change it back to private.
Hope this help.
Thomas
Updated on July 22, 2022Comments
-
Thomas almost 2 years
I want to write a unit test for a class I have. This class has a public method, and inside the public method there are calls to private methods in the same class. I want to mock the calls to those private methods. The class is similar to this:
public class SomeClass { public int somePublicMethod(int num) { int num2 = somePrivateMethod1(num); int num3 = somePrivateMethod2(num); return num2 + num3; } private int somePrivateMethod1(int num) { return 2*num; } private int somePrivateMethod2(int num) { return 3*num; } }
For my unit test I am trying to use PowerMock with Mockito and TestNG. Here is my attempt at a test that tests somePublicMethod:
import static org.powermock.api.mockito.PowerMockito.doReturn; import static org.powermock.api.mockito.PowerMockito.spy; import org.powermock.core.classloader.annotations.PrepareForTest; import org.testng.Assert; import org.testng.annotations.Test; @PrepareForTest(SomeClass.class) public class SomeClassTest { @Test public void testSomePublicMethod() throws Exception { int num = 4; SomeClass someClassSpy = spy(new SomeClass()); doReturn(8).when(someClassSpy, "somePrivateMethod1", num); doReturn(12).when(someClassSpy, "somePrivateMethod2", num); int result = someClassSpy.somePublicMethod(num); Assert.assertEquals(result, 20); } }
When I run this test I get an exception and some hints:
FAILED: testSomePublicMethod org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinished stubbing detected here: -> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31) E.g. thenReturn() may be missing. Examples of correct stubbing: when(mock.isOk()).thenReturn(true); when(mock.isOk()).thenThrow(exception); doThrow(exception).when(mock).someVoidMethod(); Hints: 1. missing thenReturn() 2. you are trying to stub a final method, you naughty developer!
I've looked at some examples online but I haven't found one that uses PowerMock with Mockito and TestNG specifically to do what I want. Can someone give me some pointers on what I could do differently?