1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht;
21
22 import org.grouplens.grapht.annotation.DefaultImplementation;
23 import org.grouplens.grapht.annotation.DefaultProvider;
24 import org.grouplens.grapht.solver.UnresolvableDependencyException;
25 import org.junit.Test;
26
27 import javax.annotation.Nullable;
28 import javax.inject.Inject;
29 import javax.inject.Provider;
30
31 import static org.hamcrest.Matchers.*;
32 import static org.junit.Assert.*;
33
34 public class SkipIfUnusableTest {
35
36
37
38 @Test
39 public void testSatisfyImplementation() throws InjectionException {
40 InjectorBuilder bld = InjectorBuilder.create();
41 bld.bind(Inner.class).to(InnerObj.class);
42 Injector inj = bld.build();
43 IfaceWithSkippableDefault obj = inj.getInstance(IfaceWithSkippableDefault.class);
44 assertThat(obj, instanceOf(DftImpl.class));
45 }
46
47
48
49
50 @Test
51 public void testSatisfyProvider() throws InjectionException {
52 InjectorBuilder bld = InjectorBuilder.create();
53 bld.bind(Inner.class).to(InnerObj.class);
54 Injector inj = bld.build();
55 IfaceWithSkippableDefaultProvider obj = inj.getInstance(IfaceWithSkippableDefaultProvider.class);
56 assertThat(obj, instanceOf(ProvidedImpl.class));
57 }
58
59
60
61
62 @Test
63 public void testSkipImplementation() {
64 InjectorBuilder bld = InjectorBuilder.create();
65 Injector inj = bld.build();
66 try {
67 IfaceWithSkippableDefault obj = inj.tryGetInstance(null, IfaceWithSkippableDefault.class);
68 assertThat(obj, nullValue());
69 } catch (InjectionException ex) {
70 fail("injection of skipped object should succeed with null object");
71 }
72 }
73
74
75
76
77 @Test
78 public void testSkipProvider() {
79 InjectorBuilder bld = InjectorBuilder.create();
80 Injector inj = bld.build();
81 try {
82 IfaceWithSkippableDefaultProvider obj = inj.tryGetInstance(null, IfaceWithSkippableDefaultProvider.class);
83 assertThat(obj, nullValue());
84 } catch (InjectionException e) {
85 fail("injection of skipped provider should succeed with null object");
86 }
87 }
88
89
90
91
92 @Test
93 public void testFailWithUnsatisfiedTransitiveDep() {
94 InjectorBuilder bld = InjectorBuilder.create();
95 bld.bind(Inner.class).to(InnerWithDep.class);
96 Injector inj = bld.build();
97 try {
98 inj.tryGetInstance(null, IfaceWithSkippableDefault.class);
99 fail("injecting a skippable default with a satisfied but instantiable dep should fail");
100 } catch (InjectionException ex) {
101 assertThat(ex, instanceOf(UnresolvableDependencyException.class));
102 }
103 }
104
105
106
107
108 @Test
109 public void testFailWithUnusableDefaultForDep() {
110 InjectorBuilder bld = InjectorBuilder.create();
111 Injector inj = bld.build();
112 try {
113 inj.getInstance(null, DefaultRequirer.class);
114 fail("injection of dep on skipped default should fail");
115 } catch (InjectionException ex) {
116 assertThat(ex, instanceOf(UnresolvableDependencyException.class));
117 }
118 }
119
120
121
122
123 @Test
124 public void testAcceptSkippedOptionalDep() {
125 InjectorBuilder bld = InjectorBuilder.create();
126 Injector inj = bld.build();
127 try {
128 OptionalDefaultRequirer obj = inj.getInstance(OptionalDefaultRequirer.class);
129 assertThat(obj, notNullValue());
130 } catch (InjectionException ex) {
131 fail("injection of component with optional dep on skipped default should succeed");
132 }
133 }
134
135
136
137
138 @Test
139 public void testFailOptionalDepHasUnmetDep() {
140 InjectorBuilder bld = InjectorBuilder.create();
141 bld.bind(Inner.class).to(InnerWithDep.class);
142 Injector inj = bld.build();
143 try {
144 OptionalDefaultRequirer obj = inj.getInstance(OptionalDefaultRequirer.class);
145 fail("injection of component with optional dep on non-skipped but uninstantiable default should fail");
146 } catch (InjectionException ex) {
147 assertThat(ex, instanceOf(UnresolvableDependencyException.class));
148 }
149 }
150
151
152
153
154 @Test
155 public void testNestedSkipping() throws InjectionException {
156 InjectorBuilder bld = InjectorBuilder.create();
157 Injector inj = bld.build();
158 Outer obj = inj.tryGetInstance(null, Outer.class);
159 assertThat(obj, nullValue());
160 }
161
162
163
164
165 interface Inner {
166 }
167
168
169
170
171 static class InnerObj implements Inner {
172 @Inject
173 public InnerObj() {}
174 }
175
176
177
178
179 static class InnerWithDep implements Inner {
180 private final String message;
181
182 @Inject
183 public InnerWithDep(String msg) {
184 message = msg;
185 }
186
187 public String getMessage() {
188 return message;
189 }
190 }
191
192
193
194
195 @DefaultImplementation(value=DftImpl.class, skipIfUnusable = true)
196 interface IfaceWithSkippableDefault {
197 Inner getInner();
198 }
199
200
201
202
203 static class DftImpl implements IfaceWithSkippableDefault {
204 private final Inner inner;
205
206 @Inject
207 public DftImpl(Inner in) {
208 inner = in;
209 }
210
211 @Override
212 public Inner getInner() {
213 return inner;
214 }
215 }
216
217
218
219
220 @DefaultProvider(value=DftProvider.class, skipIfUnusable = true)
221 interface IfaceWithSkippableDefaultProvider {
222 Inner getInner();
223 }
224
225
226
227
228 static class DftProvider implements Provider<IfaceWithSkippableDefaultProvider> {
229 private final Inner inner;
230
231 @Inject
232 public DftProvider(Inner in) {
233 inner = in;
234 }
235
236 @Override
237 public IfaceWithSkippableDefaultProvider get() {
238 return new ProvidedImpl(inner);
239 }
240 }
241
242 static class ProvidedImpl implements IfaceWithSkippableDefaultProvider {
243 private final Inner inner;
244
245 public ProvidedImpl(Inner in) {
246 inner = in;
247 }
248
249 @Override
250 public Inner getInner() {
251 return inner;
252 }
253 }
254
255 @DefaultImplementation(value = DefaultRequirer.class, skipIfUnusable = true)
256 interface Outer {}
257
258
259
260
261 static class DefaultRequirer implements Outer {
262 private final IfaceWithSkippableDefault dependency;
263
264 @Inject
265 public DefaultRequirer(IfaceWithSkippableDefault dep) {
266 dependency = dep;
267 }
268
269 public IfaceWithSkippableDefault getDependency() {
270 return dependency;
271 }
272 }
273
274
275
276
277 static class OptionalDefaultRequirer {
278 private final IfaceWithSkippableDefault dependency;
279
280 @Inject
281 public OptionalDefaultRequirer(@Nullable IfaceWithSkippableDefault dep) {
282 dependency = dep;
283 }
284
285 public IfaceWithSkippableDefault getDependency() {
286 return dependency;
287 }
288 }
289 }