-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
QuarkusTestResourceLifecycleManager.java
181 lines (152 loc) · 6.09 KB
/
QuarkusTestResourceLifecycleManager.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package io.quarkus.test.common;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.function.Predicate;
/**
* Manage the lifecycle of a test resource, for instance a H2 test server.
* <p>
* These resources are started before the first test is run, and are closed
* at the end of the test suite. They are configured via the {@link QuarkusTestResource}
* annotation, which can be placed on any class in the test suite.
*
* These can also be loaded via a service loader mechanism, however if a service
* loader is used it should not also be annotated as this will result in it being executed
* twice.
*
* Note that when using these with QuarkusUnitTest (rather than @QuarkusTest) they run
* before the ClassLoader has been setup. This means injection may not work
* as expected.
* <p>
* Due to the very early execution in the test setup lifecycle, logging does <b>not</b>
* work in such a manager.
*/
public interface QuarkusTestResourceLifecycleManager {
/**
* Start the test resource.
*
* @return A map of configuration properties that will be set for the running test
*/
Map<String, String> start();
/**
* Stop the test resource.
*/
void stop();
/**
* Set the context in which this {@link QuarkusTestResourceLifecycleManager} is being used.
* This method is executed before the {@code init} method.
*
* The {@code context} is never null.
*/
default void setContext(Context context) {
}
/**
* Arguments passed to the lifecycle manager before it starts
* These arguments are taken from {@code QuarkusTestResource#initArgs()}
*
* The {@code args} is never null
*
* @see QuarkusTestResource#initArgs()
*/
default void init(Map<String, String> initArgs) {
}
/**
* Allow each resource to provide custom injection of fields of the test class.
*
* Most implementations will likely use {@link QuarkusTestResourceLifecycleManager#inject(TestInjector)}
* as it provides a simpler way to inject into fields of tests.
*
* It is worth mentioning that this injection into the test class is not under the control of CDI and happens after CDI has
* performed
* any necessary injections into the test class.
*/
default void inject(Object testInstance) {
}
/**
* Simplifies the injection of fields of the test class by providing methods to handle the common injection cases.
*
* In situations not covered by {@link TestInjector}, user can resort to implementing
* {@link QuarkusTestResourceLifecycleManager#inject(Object)}
*
* It is worth mentioning that this injection into the test class is not under the control of CDI and happens after CDI has
* performed
* any necessary injections into the test class.
*/
default void inject(TestInjector testInjector) {
}
/**
* If multiple Test Resources are specified,
* this control the order of which they will be executed.
*
* @return The order to be executed. The larger the number, the later the Resource is invoked.
*/
default int order() {
return 0;
}
/**
* Provides methods to handle the common injection cases. See
* {@link QuarkusTestResourceLifecycleManager#inject(TestInjector)}
*/
interface TestInjector {
/**
* @param fieldValue The actual value to inject into a test field
* @param predicate User supplied predicate which can be used to determine whether or not the field should be
* set with with {@code fieldValue}
*/
void injectIntoFields(Object fieldValue, Predicate<Field> predicate);
/**
* Returns {@code true} if the field is annotated with the supplied annotation.
*/
class Annotated implements Predicate<Field> {
private final Class<? extends Annotation> annotationClass;
public Annotated(Class<? extends Annotation> annotationClass) {
this.annotationClass = annotationClass;
}
@Override
public boolean test(Field field) {
return field.getAnnotation(annotationClass) != null;
}
}
/**
* Returns {@code true} if the field can be assigned to the supplied type.
*/
class MatchesType implements Predicate<Field> {
private final Class<?> expectedFieldType;
public MatchesType(Class<?> expectedFieldType) {
this.expectedFieldType = expectedFieldType;
}
@Override
public boolean test(Field field) {
return field.getType().isAssignableFrom(expectedFieldType);
}
}
/**
* Returns {@code true} if the field is annotated with the supplied annotation and can also be assigned
* to the supplied type.
*/
class AnnotatedAndMatchesType implements Predicate<Field> {
private final Class<? extends Annotation> annotationClass;
private final Class<?> expectedFieldType;
public AnnotatedAndMatchesType(Class<? extends Annotation> annotationClass, Class<?> expectedFieldType) {
this.annotationClass = annotationClass;
this.expectedFieldType = expectedFieldType;
}
@Override
public boolean test(Field field) {
if (field.getAnnotation(annotationClass) == null) {
return false;
}
return field.getType().isAssignableFrom(expectedFieldType);
}
}
}
interface Context {
/**
* When a {@link QuarkusTestResourceLifecycleManager} is used with a type of test that supports test profiles,
* this method gives the name of the active test profile, or {@code null} if no test profile is active.
* In the case of {@code QuarkusTestProfile}, this method gives the name of the class that implements
* {@code QuarkusTestProfile}.
*/
String testProfile();
}
}