PageRenderTime 63ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/spice-inject/guice-patches/vanilla.test/com/google/inject/OverrideModuleTest.java

https://github.com/peterlynch/spice
Java | 512 lines | 411 code | 80 blank | 21 comment | 0 complexity | cb42a5872fc3269e98cab7ebf4c39bcd MD5 | raw file
  1. /**
  2. * Copyright (C) 2008 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.Guice.createInjector;
  19. import static com.google.inject.name.Names.named;
  20. import com.google.inject.name.Named;
  21. import com.google.inject.util.Modules;
  22. import static java.lang.annotation.ElementType.TYPE;
  23. import java.lang.annotation.Retention;
  24. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  25. import java.lang.annotation.Target;
  26. import java.util.Date;
  27. import java.util.concurrent.atomic.AtomicReference;
  28. import junit.framework.TestCase;
  29. /**
  30. * @author sberlin@gmail.com (Sam Berlin)
  31. */
  32. public class OverrideModuleTest extends TestCase {
  33. private static final Key<String> key2 = Key.get(String.class, named("2"));
  34. private static final Key<String> key3 = Key.get(String.class, named("3"));
  35. private static final Module EMPTY_MODULE = new Module() {
  36. public void configure(Binder binder) {}
  37. };
  38. public void testOverride() {
  39. Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B")));
  40. assertEquals("B", injector.getInstance(String.class));
  41. }
  42. public void testOverrideMultiple() {
  43. Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f))
  44. .with(newModule("B"), newModule(2), newModule(1.5d));
  45. Injector injector = createInjector(module);
  46. assertEquals("B", injector.getInstance(String.class));
  47. assertEquals(2, injector.getInstance(Integer.class).intValue());
  48. assertEquals(0.5f, injector.getInstance(Float.class));
  49. assertEquals(1.5d, injector.getInstance(Double.class));
  50. }
  51. public void testOverrideUnmatchedTolerated() {
  52. Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B")));
  53. assertEquals("B", injector.getInstance(String.class));
  54. }
  55. public void testOverrideConstant() {
  56. Module original = new AbstractModule() {
  57. @Override protected void configure() {
  58. bindConstant().annotatedWith(named("Test")).to("A");
  59. }
  60. };
  61. Module replacements = new AbstractModule() {
  62. @Override protected void configure() {
  63. bindConstant().annotatedWith(named("Test")).to("B");
  64. }
  65. };
  66. Injector injector = createInjector(Modules.override(original).with(replacements));
  67. assertEquals("B", injector.getInstance(Key.get(String.class, named("Test"))));
  68. }
  69. public void testGetProviderInModule() {
  70. Module original = new AbstractModule() {
  71. @Override protected void configure() {
  72. bind(String.class).toInstance("A");
  73. bind(key2).toProvider(getProvider(String.class));
  74. }
  75. };
  76. Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE));
  77. assertEquals("A", injector.getInstance(String.class));
  78. assertEquals("A", injector.getInstance(key2));
  79. }
  80. public void testOverrideWhatGetProviderProvided() {
  81. Module original = new AbstractModule() {
  82. @Override protected void configure() {
  83. bind(String.class).toInstance("A");
  84. bind(key2).toProvider(getProvider(String.class));
  85. }
  86. };
  87. Module replacements = newModule("B");
  88. Injector injector = createInjector(Modules.override(original).with(replacements));
  89. assertEquals("B", injector.getInstance(String.class));
  90. assertEquals("B", injector.getInstance(key2));
  91. }
  92. public void testOverrideUsingOriginalsGetProvider() {
  93. Module original = new AbstractModule() {
  94. @Override protected void configure() {
  95. bind(String.class).toInstance("A");
  96. bind(key2).toInstance("B");
  97. }
  98. };
  99. Module replacements = new AbstractModule() {
  100. @Override protected void configure() {
  101. bind(String.class).toProvider(getProvider(key2));
  102. }
  103. };
  104. Injector injector = createInjector(Modules.override(original).with(replacements));
  105. assertEquals("B", injector.getInstance(String.class));
  106. assertEquals("B", injector.getInstance(key2));
  107. }
  108. public void testOverrideOfOverride() {
  109. Module original = new AbstractModule() {
  110. @Override protected void configure() {
  111. bind(String.class).toInstance("A1");
  112. bind(key2).toInstance("A2");
  113. bind(key3).toInstance("A3");
  114. }
  115. };
  116. Module replacements1 = new AbstractModule() {
  117. @Override protected void configure() {
  118. bind(String.class).toInstance("B1");
  119. bind(key2).toInstance("B2");
  120. }
  121. };
  122. Module overrides = Modules.override(original).with(replacements1);
  123. Module replacements2 = new AbstractModule() {
  124. @Override protected void configure() {
  125. bind(String.class).toInstance("C1");
  126. bind(key3).toInstance("C3");
  127. }
  128. };
  129. Injector injector = createInjector(Modules.override(overrides).with(replacements2));
  130. assertEquals("C1", injector.getInstance(String.class));
  131. assertEquals("B2", injector.getInstance(key2));
  132. assertEquals("C3", injector.getInstance(key3));
  133. }
  134. public void testOverridesTwiceFails() {
  135. Module original = newModule("A");
  136. Module replacements = new AbstractModule() {
  137. @Override protected void configure() {
  138. bind(String.class).toInstance("B");
  139. bind(String.class).toInstance("C");
  140. }
  141. };
  142. Module module = Modules.override(original).with(replacements);
  143. try {
  144. createInjector(module);
  145. fail();
  146. } catch (CreationException expected) {
  147. assertContains(expected.getMessage(), "A binding to java.lang.String "
  148. + "was already configured at " + replacements.getClass().getName(),
  149. "at " + replacements.getClass().getName());
  150. }
  151. }
  152. public void testOverridesDoesntFixTwiceBoundInOriginal() {
  153. Module original = new AbstractModule() {
  154. @Override protected void configure() {
  155. bind(String.class).toInstance("A");
  156. bind(String.class).toInstance("B");
  157. }
  158. };
  159. Module replacements = new AbstractModule() {
  160. @Override protected void configure() {
  161. bind(String.class).toInstance("C");
  162. }
  163. };
  164. Module module = Modules.override(original).with(replacements);
  165. try {
  166. createInjector(module);
  167. fail();
  168. } catch (CreationException expected) {
  169. assertContains(expected.getMessage(), "1) A binding to java.lang.String "
  170. + "was already configured at " + replacements.getClass().getName(),
  171. "at " + original.getClass().getName());
  172. }
  173. }
  174. public void testStandardScopeAnnotation() {
  175. final SingleUseScope scope = new SingleUseScope();
  176. Module module = new AbstractModule() {
  177. protected void configure() {
  178. bindScope(TestScopeAnnotation.class, scope);
  179. bind(String.class).in(TestScopeAnnotation.class);
  180. }
  181. };
  182. assertFalse(scope.used);
  183. Guice.createInjector(module);
  184. assertTrue(scope.used);
  185. }
  186. public void testOverrideUntargettedBinding() {
  187. Module original = new AbstractModule() {
  188. @Override protected void configure() {
  189. bind(Date.class);
  190. }
  191. };
  192. Module replacements = new AbstractModule() {
  193. @Override protected void configure() {
  194. bind(Date.class).toInstance(new Date(0));
  195. }
  196. };
  197. Injector injector = createInjector(Modules.override(original).with(replacements));
  198. assertEquals(0, injector.getInstance(Date.class).getTime());
  199. }
  200. public void testOverrideScopeAnnotation() {
  201. final Scope scope = new Scope() {
  202. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  203. throw new AssertionError("Should not be called");
  204. }
  205. };
  206. final SingleUseScope replacementScope = new SingleUseScope();
  207. Module original = new AbstractModule() {
  208. @Override protected void configure() {
  209. bindScope(TestScopeAnnotation.class, scope);
  210. bind(Date.class).in(TestScopeAnnotation.class);
  211. }
  212. };
  213. Module replacements = new AbstractModule() {
  214. @Override protected void configure() {
  215. bindScope(TestScopeAnnotation.class, replacementScope);
  216. }
  217. };
  218. Injector injector = createInjector(Modules.override(original).with(replacements));
  219. injector.getInstance(Date.class);
  220. assertTrue(replacementScope.used);
  221. }
  222. public void testFailsIfOverridenScopeInstanceHasBeenUsed() {
  223. final Scope scope = new Scope() {
  224. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  225. return unscoped;
  226. }
  227. @Override public String toString() {
  228. return "ORIGINAL SCOPE";
  229. }
  230. };
  231. Module original = new AbstractModule() {
  232. @Override protected void configure() {
  233. bindScope(TestScopeAnnotation.class, scope);
  234. bind(Date.class).in(scope);
  235. }
  236. };
  237. Module replacements = new AbstractModule() {
  238. @Override protected void configure() {
  239. bindScope(TestScopeAnnotation.class, new SingleUseScope());
  240. }
  241. };
  242. try {
  243. createInjector(Modules.override(original).with(replacements));
  244. fail("Exception expected");
  245. } catch (CreationException e) {
  246. assertContains(e.getMessage(),
  247. "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.",
  248. "at ", getClass().getName(), ".configure(");
  249. }
  250. }
  251. public void testOverrideIsLazy() {
  252. final AtomicReference<String> value = new AtomicReference<String>("A");
  253. Module overridden = Modules.override(new AbstractModule() {
  254. protected void configure() {
  255. bind(String.class).annotatedWith(named("original")).toInstance(value.get());
  256. }
  257. }).with(new AbstractModule() {
  258. protected void configure() {
  259. bind(String.class).annotatedWith(named("override")).toInstance(value.get());
  260. }
  261. });
  262. // the value.get() call should be deferred until Guice.createInjector
  263. value.set("B");
  264. Injector injector = Guice.createInjector(overridden);
  265. assertEquals("B", injector.getInstance(Key.get(String.class, named("original"))));
  266. assertEquals("B", injector.getInstance(Key.get(String.class, named("override"))));
  267. }
  268. public void testOverridePrivateModuleOverPrivateModule() {
  269. Module exposes5and6 = new AbstractModule() {
  270. protected void configure() {
  271. install(new PrivateModule() {
  272. protected void configure() {
  273. bind(Integer.class).toInstance(5);
  274. expose(Integer.class);
  275. bind(Character.class).toInstance('E');
  276. }
  277. });
  278. install(new PrivateModule() {
  279. protected void configure() {
  280. bind(Long.class).toInstance(6L);
  281. expose(Long.class);
  282. bind(Character.class).toInstance('F');
  283. }
  284. });
  285. }
  286. };
  287. AbstractModule exposes15 = new AbstractModule() {
  288. protected void configure() {
  289. install(new PrivateModule() {
  290. protected void configure() {
  291. bind(Integer.class).toInstance(15);
  292. expose(Integer.class);
  293. bind(Character.class).toInstance('G');
  294. }
  295. });
  296. install(new PrivateModule() {
  297. protected void configure() {
  298. bind(Character.class).toInstance('H');
  299. }
  300. });
  301. }
  302. };
  303. // override forwards
  304. Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15));
  305. assertEquals(15, injector.getInstance(Integer.class).intValue());
  306. assertEquals(6L, injector.getInstance(Long.class).longValue());
  307. // and in reverse order
  308. Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6));
  309. assertEquals(5, reverse.getInstance(Integer.class).intValue());
  310. assertEquals(6L, reverse.getInstance(Long.class).longValue());
  311. }
  312. public void testOverrideModuleAndPrivateModule() {
  313. Module exposes5 = new PrivateModule() {
  314. protected void configure() {
  315. bind(Integer.class).toInstance(5);
  316. expose(Integer.class);
  317. }
  318. };
  319. Module binds15 = new AbstractModule() {
  320. protected void configure() {
  321. bind(Integer.class).toInstance(15);
  322. }
  323. };
  324. Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
  325. assertEquals(15, injector.getInstance(Integer.class).intValue());
  326. Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5));
  327. assertEquals(5, reverse.getInstance(Integer.class).intValue());
  328. }
  329. public void testOverrideDeepExpose() {
  330. final AtomicReference<Provider<Character>> charAProvider
  331. = new AtomicReference<Provider<Character>>();
  332. Module exposes5 = new PrivateModule() {
  333. protected void configure() {
  334. install(new PrivateModule() {
  335. protected void configure() {
  336. bind(Integer.class).toInstance(5);
  337. expose(Integer.class);
  338. charAProvider.set(getProvider(Character.class));
  339. bind(Character.class).toInstance('A');
  340. }
  341. });
  342. expose(Integer.class);
  343. }
  344. };
  345. Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE));
  346. assertEquals(5, injector.getInstance(Integer.class).intValue());
  347. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  348. injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5));
  349. assertEquals(5, injector.getInstance(Integer.class).intValue());
  350. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  351. final AtomicReference<Provider<Character>> charBProvider
  352. = new AtomicReference<Provider<Character>>();
  353. Module binds15 = new AbstractModule() {
  354. protected void configure() {
  355. bind(Integer.class).toInstance(15);
  356. install(new PrivateModule() {
  357. protected void configure() {
  358. charBProvider.set(getProvider(Character.class));
  359. bind(Character.class).toInstance('B');
  360. }
  361. });
  362. }
  363. };
  364. injector = Guice.createInjector(Modules.override(binds15).with(exposes5));
  365. assertEquals(5, injector.getInstance(Integer.class).intValue());
  366. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  367. assertEquals('B', charBProvider.getAndSet(null).get().charValue());
  368. injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
  369. assertEquals(15, injector.getInstance(Integer.class).intValue());
  370. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  371. assertEquals('B', charBProvider.getAndSet(null).get().charValue());
  372. }
  373. @Retention(RUNTIME)
  374. @Target(TYPE)
  375. @ScopeAnnotation
  376. private static @interface TestScopeAnnotation {}
  377. private static class SingleUseScope implements Scope {
  378. boolean used = false;
  379. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  380. assertFalse(used);
  381. used = true;
  382. return unscoped;
  383. }
  384. }
  385. private static <T> Module newModule(final T bound) {
  386. return new AbstractModule() {
  387. @Override protected void configure() {
  388. @SuppressWarnings("unchecked")
  389. Class<T> type = (Class<T>) bound.getClass();
  390. bind(type).toInstance(bound);
  391. }
  392. };
  393. }
  394. private static final String RESULT = "RESULT";
  395. private static final String PRIVATE_INPUT = "PRIVATE_INPUT";
  396. private static final String OVERRIDDEN_INPUT = "FOO";
  397. private static final String OVERRIDDEN_RESULT = "Size: 3";
  398. private static final Key<String> RESULT_KEY = Key.get(String.class, named(RESULT));
  399. private static final Key<String> INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT));
  400. public void testExposedBindingOverride() throws Exception {
  401. Injector inj = Guice.createInjector(
  402. Modules.override(new ExampleModule()).with(
  403. new AbstractModule() {
  404. @Override protected void configure() {
  405. bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT);
  406. }
  407. }));
  408. assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  409. }
  410. public void testPrivateBindingOverride() throws Exception {
  411. Injector inj = Guice.createInjector(
  412. Modules.override(new ExampleModule()).with(
  413. new AbstractModule() {
  414. @Override protected void configure() {
  415. bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT);
  416. }
  417. }));
  418. assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  419. }
  420. public static class ExampleModule extends PrivateModule {
  421. @Provides @Exposed @Named(RESULT)
  422. public String provideResult(@Named(PRIVATE_INPUT) String input) {
  423. return "Size: " + input.length();
  424. }
  425. @Provides @Named(PRIVATE_INPUT)
  426. public String provideInput() {
  427. return "Hello World";
  428. }
  429. @Override protected void configure() {
  430. }
  431. }
  432. }