PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/core/test/com/google/inject/InjectorTest.java

https://gitlab.com/metamorphiccode/guice
Java | 413 lines | 314 code | 80 blank | 19 comment | 1 complexity | a4a5a3766cfdb6525c862f3bc88d468d MD5 | raw file
  1. /**
  2. * Copyright (C) 2006 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.inject;
  17. import static com.google.inject.Asserts.assertContains;
  18. import static com.google.inject.Asserts.assertNotSerializable;
  19. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  20. import junit.framework.TestCase;
  21. import java.io.IOException;
  22. import java.lang.annotation.Retention;
  23. import java.util.concurrent.Callable;
  24. import java.util.concurrent.ExecutionException;
  25. import java.util.concurrent.ExecutorService;
  26. import java.util.concurrent.Executors;
  27. import java.util.concurrent.Future;
  28. import java.util.concurrent.atomic.AtomicReference;
  29. /**
  30. * @author crazybob@google.com (Bob Lee)
  31. */
  32. public class InjectorTest extends TestCase {
  33. @Retention(RUNTIME)
  34. @BindingAnnotation @interface Other {}
  35. @Retention(RUNTIME)
  36. @BindingAnnotation @interface S {}
  37. @Retention(RUNTIME)
  38. @BindingAnnotation @interface I {}
  39. public void testToStringDoesNotInfinitelyRecurse() {
  40. Injector injector = Guice.createInjector(Stage.TOOL);
  41. injector.toString();
  42. injector.getBinding(Injector.class).toString();
  43. }
  44. public void testProviderMethods() throws CreationException {
  45. final SampleSingleton singleton = new SampleSingleton();
  46. final SampleSingleton other = new SampleSingleton();
  47. Injector injector = Guice.createInjector(new AbstractModule() {
  48. protected void configure() {
  49. bind(SampleSingleton.class).toInstance(singleton);
  50. bind(SampleSingleton.class)
  51. .annotatedWith(Other.class)
  52. .toInstance(other);
  53. }
  54. });
  55. assertSame(singleton,
  56. injector.getInstance(Key.get(SampleSingleton.class)));
  57. assertSame(singleton, injector.getInstance(SampleSingleton.class));
  58. assertSame(other,
  59. injector.getInstance(Key.get(SampleSingleton.class, Other.class)));
  60. }
  61. static class SampleSingleton {}
  62. public void testInjection() throws CreationException {
  63. Injector injector = createFooInjector();
  64. Foo foo = injector.getInstance(Foo.class);
  65. assertEquals("test", foo.s);
  66. assertEquals("test", foo.bar.getTee().getS());
  67. assertSame(foo.bar, foo.copy);
  68. assertEquals(5, foo.i);
  69. assertEquals(5, foo.bar.getI());
  70. // Test circular dependency.
  71. assertSame(foo.bar, foo.bar.getTee().getBar());
  72. }
  73. private Injector createFooInjector() throws CreationException {
  74. return Guice.createInjector(new AbstractModule() {
  75. protected void configure() {
  76. bind(Bar.class).to(BarImpl.class);
  77. bind(Tee.class).to(TeeImpl.class);
  78. bindConstant().annotatedWith(S.class).to("test");
  79. bindConstant().annotatedWith(I.class).to(5);
  80. }
  81. });
  82. }
  83. public void testGetInstance() throws CreationException {
  84. Injector injector = createFooInjector();
  85. Bar bar = injector.getInstance(Key.get(Bar.class));
  86. assertEquals("test", bar.getTee().getS());
  87. assertEquals(5, bar.getI());
  88. }
  89. public void testIntAndIntegerAreInterchangeable()
  90. throws CreationException {
  91. Injector injector = Guice.createInjector(new AbstractModule() {
  92. protected void configure() {
  93. bindConstant().annotatedWith(I.class).to(5);
  94. }
  95. });
  96. IntegerWrapper iw = injector.getInstance(IntegerWrapper.class);
  97. assertEquals(5, (int) iw.i);
  98. }
  99. public void testInjectorApiIsNotSerializable() throws IOException {
  100. Injector injector = Guice.createInjector();
  101. assertNotSerializable(injector);
  102. assertNotSerializable(injector.getProvider(String.class));
  103. assertNotSerializable(injector.getBinding(String.class));
  104. for (Binding<?> binding : injector.getBindings().values()) {
  105. assertNotSerializable(binding);
  106. }
  107. }
  108. static class IntegerWrapper {
  109. @Inject @I Integer i;
  110. }
  111. static class Foo {
  112. @Inject Bar bar;
  113. @Inject Bar copy;
  114. @Inject @S String s;
  115. int i;
  116. @Inject
  117. void setI(@I int i) {
  118. this.i = i;
  119. }
  120. }
  121. interface Bar {
  122. Tee getTee();
  123. int getI();
  124. }
  125. @Singleton
  126. static class BarImpl implements Bar {
  127. @Inject @I int i;
  128. Tee tee;
  129. @Inject
  130. void initialize(Tee tee) {
  131. this.tee = tee;
  132. }
  133. public Tee getTee() {
  134. return tee;
  135. }
  136. public int getI() {
  137. return i;
  138. }
  139. }
  140. interface Tee {
  141. String getS();
  142. Bar getBar();
  143. }
  144. static class TeeImpl implements Tee {
  145. final String s;
  146. @Inject Bar bar;
  147. @Inject
  148. TeeImpl(@S String s) {
  149. this.s = s;
  150. }
  151. public String getS() {
  152. return s;
  153. }
  154. public Bar getBar() {
  155. return bar;
  156. }
  157. }
  158. public void testInjectStatics() throws CreationException {
  159. Guice.createInjector(new AbstractModule() {
  160. protected void configure() {
  161. bindConstant().annotatedWith(S.class).to("test");
  162. bindConstant().annotatedWith(I.class).to(5);
  163. requestStaticInjection(Static.class);
  164. }
  165. });
  166. assertEquals("test", Static.s);
  167. assertEquals(5, Static.i);
  168. }
  169. public void testInjectStaticInterface() {
  170. try {
  171. Guice.createInjector(new AbstractModule() {
  172. protected void configure() {
  173. requestStaticInjection(Interface.class);
  174. }
  175. });
  176. fail();
  177. } catch(CreationException ce) {
  178. assertEquals(1, ce.getErrorMessages().size());
  179. Asserts.assertContains(
  180. ce.getMessage(),
  181. "1) " + Interface.class.getName()
  182. + " is an interface, but interfaces have no static injection points.",
  183. "at " + InjectorTest.class.getName(),
  184. "configure");
  185. }
  186. }
  187. private static interface Interface {}
  188. static class Static {
  189. @Inject @I static int i;
  190. static String s;
  191. @Inject static void setS(@S String s) {
  192. Static.s = s;
  193. }
  194. }
  195. public void testPrivateInjection() throws CreationException {
  196. Injector injector = Guice.createInjector(new AbstractModule() {
  197. protected void configure() {
  198. bind(String.class).toInstance("foo");
  199. bind(int.class).toInstance(5);
  200. }
  201. });
  202. Private p = injector.getInstance(Private.class);
  203. assertEquals("foo", p.fromConstructor);
  204. assertEquals(5, p.fromMethod);
  205. }
  206. static class Private {
  207. String fromConstructor;
  208. int fromMethod;
  209. @Inject
  210. private Private(String fromConstructor) {
  211. this.fromConstructor = fromConstructor;
  212. }
  213. @Inject
  214. private void setInt(int i) {
  215. this.fromMethod = i;
  216. }
  217. }
  218. public void testProtectedInjection() throws CreationException {
  219. Injector injector = Guice.createInjector(new AbstractModule() {
  220. protected void configure() {
  221. bind(String.class).toInstance("foo");
  222. bind(int.class).toInstance(5);
  223. }
  224. });
  225. Protected p = injector.getInstance(Protected.class);
  226. assertEquals("foo", p.fromConstructor);
  227. assertEquals(5, p.fromMethod);
  228. }
  229. static class Protected {
  230. String fromConstructor;
  231. int fromMethod;
  232. @Inject
  233. protected Protected(String fromConstructor) {
  234. this.fromConstructor = fromConstructor;
  235. }
  236. @Inject
  237. protected void setInt(int i) {
  238. this.fromMethod = i;
  239. }
  240. }
  241. public void testInstanceInjectionHappensAfterFactoriesAreSetUp() {
  242. Guice.createInjector(new AbstractModule() {
  243. protected void configure() {
  244. bind(Object.class).toInstance(new Object() {
  245. @Inject Runnable r;
  246. });
  247. bind(Runnable.class).to(MyRunnable.class);
  248. }
  249. });
  250. }
  251. public void testSubtypeNotProvided() {
  252. try {
  253. Guice.createInjector().getInstance(Money.class);
  254. fail();
  255. } catch (ProvisionException expected) {
  256. assertContains(expected.getMessage(),
  257. Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(),
  258. "while locating ", Tree.class.getName(),
  259. "while locating ", Money.class.getName());
  260. }
  261. }
  262. public void testNotASubtype() {
  263. try {
  264. Guice.createInjector().getInstance(PineTree.class);
  265. fail();
  266. } catch (ConfigurationException expected) {
  267. assertContains(expected.getMessage(),
  268. Tree.class.getName() + " doesn't extend " + PineTree.class.getName(),
  269. "while locating ", PineTree.class.getName());
  270. }
  271. }
  272. public void testRecursiveImplementationType() {
  273. try {
  274. Guice.createInjector().getInstance(SeaHorse.class);
  275. fail();
  276. } catch (ConfigurationException expected) {
  277. assertContains(expected.getMessage(),
  278. "@ImplementedBy points to the same class it annotates.",
  279. "while locating ", SeaHorse.class.getName());
  280. }
  281. }
  282. public void testRecursiveProviderType() {
  283. try {
  284. Guice.createInjector().getInstance(Chicken.class);
  285. fail();
  286. } catch (ConfigurationException expected) {
  287. assertContains(expected.getMessage(),
  288. "@ProvidedBy points to the same class it annotates",
  289. "while locating ", Chicken.class.getName());
  290. }
  291. }
  292. static class MyRunnable implements Runnable {
  293. public void run() {}
  294. }
  295. @ProvidedBy(Tree.class)
  296. static class Money {}
  297. static class Tree implements Provider<Object> {
  298. public Object get() {
  299. return "Money doesn't grow on trees";
  300. }
  301. }
  302. @ImplementedBy(Tree.class)
  303. static class PineTree extends Tree {}
  304. @ImplementedBy(SeaHorse.class)
  305. static class SeaHorse {}
  306. @ProvidedBy(Chicken.class)
  307. static class Chicken implements Provider<Chicken> {
  308. public Chicken get() {
  309. return this;
  310. }
  311. }
  312. public void testJitBindingFromAnotherThreadDuringInjection() {
  313. final ExecutorService executorService = Executors.newSingleThreadExecutor();
  314. final AtomicReference<JustInTime> got = new AtomicReference<JustInTime>();
  315. Guice.createInjector(new AbstractModule() {
  316. protected void configure() {
  317. requestInjection(new Object() {
  318. @Inject void initialize(final Injector injector)
  319. throws ExecutionException, InterruptedException {
  320. Future<JustInTime> future = executorService.submit(new Callable<JustInTime>() {
  321. public JustInTime call() throws Exception {
  322. return injector.getInstance(JustInTime.class);
  323. }
  324. });
  325. got.set(future.get());
  326. }
  327. });
  328. }
  329. });
  330. assertNotNull(got.get());
  331. }
  332. static class JustInTime {}
  333. }