I have a chain of methods in my class. Here is the simplified version:
public class SomeClass {
public String run (String someString1, String someString2, String someString3) {
return firstAction(someString1, someString2, someString3);
}
private String firstAction(String someString1, String someString2, String someString3) {
return someString1 + secondAction(someString2, someString3);
}
private String secondAction(String someString2, String someString3) {
return someString2 + someString3;
}
}
I can test "secondAction" using the reflection. Or I can test "run" using PowerMock to mock "firstAction". Individual tests work fine. But when I try to test both methods at the same time it ends with error. The same problem in case of testing "firstAction" (using reflection) and mocking "secondAction" (using PowerMock).
@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {
private Method getSecondActionMethod() throws NoSuchMethodException {
Method method = SomeClass.class.getDeclaredMethod("secondAction", String.class, String.class);
method.setAccessible(true);
return method;
}
@Test
public void runTest() throws Exception {
SomeClass someClassSpy = PowerMock.createPartialMock(SomeClass.class, "firstAction");
PowerMock.expectPrivate(someClassSpy, "firstAction", "Hello", ", ", "World!").andReturn("Hello, World!");
PowerMock.replay(someClassSpy);
assertEquals("Hello, World!", someClassSpy.run("Hello", ", ", "World!"));
PowerMock.verify(someClassSpy);
}
@Test
public void secondActionTest () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
SomeClass someClass = new SomeClass();
assertEquals("Hello, World!", getSecondActionMethod().invoke(someClass, "Hello, ", "World!"));
}
}
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:200)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:194)
at org.powermock.reflect.internal.WhiteboxImpl.doGetAllMethods(WhiteboxImpl.java:1508)
at org.powermock.reflect.internal.WhiteboxImpl.getAllMethods(WhiteboxImpl.java:1482)
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1750)
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1789)
at org.powermock.reflect.internal.WhiteboxImpl.getBestMethodCandidate(WhiteboxImpl.java:1008)
at org.powermock.core.MockInvocation.findMethodToInvoke(MockInvocation.java:58)
at org.powermock.core.MockInvocation.init(MockInvocation.java:35)
at org.powermock.core.MockInvocation.<init>(MockInvocation.java:22)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:155)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:138)
at somePackage.SomeClassTest.getSecondActionMethod(SomeClassTest.java:26)
at somePackage.SomeClassTest.secondActionTest(SomeClassTest.java:54)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:326)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:117)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
Please help me to understand this error. Is there another way to test and mock private methods at the same time? Especially when you need to mock a private method called inside another private method. Please do not suggest something like:
- Changing private to public/protected.
- Combining all private methods into one.
- Not to test private methods.
Aucun commentaire:
Enregistrer un commentaire