This repository has been archived by the owner on Feb 17, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathSPublicMethodInvocationTest.java
117 lines (94 loc) · 4.34 KB
/
SPublicMethodInvocationTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package none.cvg.methods;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import none.cvg.DemoClass;
import none.cvg.HandlesKataDisplayNames;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static none.cvg.ErrorMessages.REFLECTION_FAILURE;
import static none.cvg.ErrorMessages.TEST_FAILURE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
/*
* DONE:
* This test aims at using MethodHandles to invoke a public method on a class.
* Each solved test shows how this can be achieved with the traditional reflection calls.
* Each unsolved test provides a few hints that will allow the kata-taker to manually solve
* the exercise to achieve the same goal with MethodHandles.
*/
@DisplayNameGeneration(HandlesKataDisplayNames.class)
@DisplayName("Invoke DemoClass.publicMethod(String)")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class SPublicMethodInvocationTest {
@Test
@Tag("PASSING")
@Order(1)
public void reflectionPublicMethod() {
String expectedOutput = "[DemoClass] - Public method - via reflection";
try {
// Find the method on the class via a getMethod.
Method publicMethod =
DemoClass.class.getMethod("publicMethod",
String.class);
DemoClass demoClass = new DemoClass();
assertEquals(expectedOutput,
publicMethod.invoke(demoClass, "via reflection"),
"Reflection invocation failed");
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
fail(REFLECTION_FAILURE.getValue() + e.getMessage());
}
}
@Test
@Tag("PASSING")
@Order(2)
public void methodHandlePublicMethod() {
String expectedOutput = "[DemoClass] - Public method - via Method Handles";
/*
* DONE:
* Get a public lookup from java.lang.invoke.MethodHandles
* Public parts of a class are looked up via "public lookups"
* Check API: java.lang.invoke.MethodHandles.publicLookup()
*/
MethodHandles.Lookup publicMethodHandlesLookup = MethodHandles.publicLookup();
/*
* DONE:
* Replace the "null"s with valid values to extract a method signature for publicMethod.
* Create a methodType instance that matches the signature of what we wish to invoke
* HINT: The publicMethod() returns a String and accepts a String parameter
* Check API: java.lang.invoke.MethodType.methodType(?, ?)
*/
MethodType methodType = MethodType.methodType(String.class, String.class);
try {
/*
* DONE:
* Replace the "null"s with appropriate values to get a handle to publicMethod.
* "Find" a method of the class via the Lookup instance,
* based on the methodType described above and the method name.
* Public methods can be searched via the findVirtual() method.
* Check API: java.lang.invoke.MethodHandles.Lookup.findVirtual(?, ?, ?)
*/
MethodHandle publicMethodHandle =
publicMethodHandlesLookup.findVirtual(DemoClass.class,
"publicMethod", methodType); // Class, Method name, MethodType
DemoClass demoClass = new DemoClass();
assertEquals(expectedOutput,
publicMethodHandle.invoke(demoClass,
"via Method Handles"),
"Method handles invocation failed");
} catch (NoSuchMethodException | IllegalAccessException e) {
fail("Failed to execute a public method invocation via Method Handles: "
+ e.getMessage());
} catch (Throwable t) {
// invoke throws a Throwable (hence catching Throwable separately).
fail(TEST_FAILURE.getValue() + t.getMessage());
}
}
}