In short, I have a set of generated source code that I need to be able to dynamically mock based on external, non-Java configuration - they follow no consistent pattern / implement any interfaces other than being static, meaning I can only know how to mock a method at runtime and need to use PowerMockito to do so.
Say that I have this class:
public class SomeClass {
public static void doSomething(Integer i) {
throw new RuntimeException();
}
}
And I simply want to mock doSomething / have it not throw exceptions. To do that simply / without any of the complexity I mention in my use case, I could do this:
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
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 TestSomeClass {
@Test
public void testDoSomethingSimple() throws Exception {
PowerMockito.spy(SomeClass.class);
PowerMockito.doNothing().when(SomeClass.class, "doSomething", any(Integer.class));
SomeClass.doSomething(5);
}
}
Which works fine.
This changes however when we step back and try to address my needs, and move complexity to something like this:
@Test
public void testDoSomething() throws Exception {
// Below showing how everything could be externally-driven
testDoSomething("SomeClass", "doSomething", "java.lang.Integer");
SomeClass.doSomething(5);
}
public void testDoSomething(
final String canonicalClassName, final String methodName, final String... canonicalParameterClassNames)
throws Exception {
final Class<?> clazz = Class.forName(canonicalClassName);
PowerMockito.spy(clazz);
final Object[] argumentMatchers = new Object[canonicalParameterClassNames.length];
for (int i = 0; i < canonicalParameterClassNames.length; i++) {
argumentMatchers[i] = any(Class.forName(canonicalParameterClassNames[i]));
}
PowerMockito.doNothing().when(clazz, methodName, argumentMatchers);
}
After much head scratching, managed to replicate this error much more succinctly:
@Test
public void testDoSomethingIssueIsolated() throws Exception {
PowerMockito.spy(SomeClass.class);
Object matcher = any(Integer.class);
PowerMockito.doNothing().when(SomeClass.class, "doSomething", matcher);
SomeClass.doSomething(5);
}
Seemingly indicating that what's causing this issue is where the calls to create the argument matchers are, which is rather odd.