Reputation: 349
I need the test to run through the method. I have this class:
public class MyClass {
private void myClassMethod(Tuple5<List<Index>, List<Category>, Optional<Category>, List<CategoryIndex>, List<TopIndex>> objects) {
List<Index> indexes = objects.getT1();
List<Category> categories = objects.getT2();
Optional<Category> defaultCategory = objects.getT3();
List<CategoryIndex> categoryIndexes = objects.getT4();
List<TopIndex> topIndexes = objects.getT5();
}
I am not let to change this class. I can't change the method's visibility from private to public or add another method to the class. I am not let to write a single character in this class.
So I wrote this test:
// here are some mocks...
@InjectMocks
private MyClass myClass;
@Test
public void testMyClassMethod() throws Exception {
Class[] cArg = new Class[1];
cArg[0] = Tuple5.class;
Method method = MyClass.class.getDeclaredMethod("myClass", cArg);
method.setAccessible(true);
List<Index> indexList = new ArrayList<>();
List<Category> categoryList = new ArrayList<>();
Optional<Category> categoryOptional = Optional.empty();
List<CategoryIndex> categoryIndexList = new ArrayList<>();
List<TopIndex> topIndexList = new ArrayList<>();
Quintet<List<Index>, List<Category>, Optional<Category>, List<CategoryIndex>, List<TopIndex>>[] arr = new Quintet[1];
arr[0] = Quintet.with(indexList, categoryList, categoryOptional, categoryIndexList, topIndexList);
method.invoke(myClass, arr);
}
If I try to run, the last line (method.invoke(myClass, arr)
) throws this exception:
java.lang.IllegalArgumentException: argument type mismatch at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at myTestPackage.testMyClassMethod(MyClassTest.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.util.ArrayList.forEach(Unknown Source) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.util.ArrayList.forEach(Unknown Source) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197) at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128) at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
If I could make a Tuple5 array, it might be okay... But it's not possible. Any idea?
Thanks in advance.
Upvotes: 0
Views: 158
Reputation: 103608
Java is nominally typed. The type of thing is decided entirely by its name, and its structure has absolutely no bearing on matters whatsoever.
What does that mean?
It means that an instance of this:
class Gun {
void shoot(Person p) {
...
}
}
and this:
class Camera {
void shoot(Person p) {
...
}
}
are as related as guns and grandmas are, i.e. not at all.
You can try to capture the notion of 'has the ability to shoot a person':
interface Shooter {
void shoot(Person p) { ... }
}
and java will just not allow this. This is not going to work:
Shooter s = new Camera(); // nope
I picked 'Gun' and 'Camera' on purpose, of course: It shows WHY java is like this. Java takes the position that the concept of homonyms (same word, different meaning) is a thing. Many languages, such as javascript and python, disregard the idea that homonyms are a thing.
Java avoids homonyms by demanding package statements. The full 'name' of a thing includes the name of the method, the name of the type it is in, and the package that it is in, at which point homonyms (in the java worldview) have been eliminated. com.smithandwesson.Gun.shoot(Person p)
has a singular meaning in javaland; it is interchangible with any other thing called com.smithandwesson.Gun.shoot(Person p)
*.
As a consequence, the fact that whatever Quintet
is, that it LOOKS like a Tuple5
, has no meaning to java. a Quentet is not a Tuple5 because the names don't match. end of story.
The only objects you can pass for a parameter of type Tuple5
is either something derived from new Tuple5()
or something derived from new X()
, where X is some concrete type that is a subtype of Tuple5; it is defined as public class X extends Tuple5
, or as public class X implements Tuple5
, or as public class X extends/implements Y
, where Y extends/implements Tuple5 or some subtype thereof.
There is additionally no way to tell java: Yeah yeah yeah. Stop being such a worrywart. Treat my gun as a camera puhlease!
*) Not really; classloaders factor into it too, but it's mostly true.
Upvotes: 0