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

/core/test/com/google/inject/util/OverrideModuleTest.java

https://gitlab.com/metamorphiccode/guice
Java | 731 lines | 609 code | 99 blank | 23 comment | 17 complexity | af3d4fd1c09632988c7ce302bb46e519 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.util;
  17. import static com.google.inject.Asserts.asModuleChain;
  18. import static com.google.inject.Asserts.assertContains;
  19. import static com.google.inject.Guice.createInjector;
  20. import static com.google.inject.name.Names.named;
  21. import static java.lang.annotation.ElementType.METHOD;
  22. import static java.lang.annotation.ElementType.TYPE;
  23. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  24. import com.google.common.base.Objects;
  25. import com.google.common.collect.ImmutableSet;
  26. import com.google.inject.AbstractModule;
  27. import com.google.inject.Binder;
  28. import com.google.inject.Binding;
  29. import com.google.inject.CreationException;
  30. import com.google.inject.Exposed;
  31. import com.google.inject.Guice;
  32. import com.google.inject.Injector;
  33. import com.google.inject.Key;
  34. import com.google.inject.Module;
  35. import com.google.inject.PrivateModule;
  36. import com.google.inject.Provider;
  37. import com.google.inject.Provides;
  38. import com.google.inject.Scope;
  39. import com.google.inject.ScopeAnnotation;
  40. import com.google.inject.Stage;
  41. import com.google.inject.name.Named;
  42. import com.google.inject.name.Names;
  43. import com.google.inject.spi.InjectionPoint;
  44. import com.google.inject.spi.ModuleAnnotatedMethodScanner;
  45. import junit.framework.TestCase;
  46. import java.lang.annotation.Annotation;
  47. import java.lang.annotation.Documented;
  48. import java.lang.annotation.Retention;
  49. import java.lang.annotation.Target;
  50. import java.util.Date;
  51. import java.util.Set;
  52. import java.util.concurrent.atomic.AtomicReference;
  53. /**
  54. * @author sberlin@gmail.com (Sam Berlin)
  55. */
  56. public class OverrideModuleTest extends TestCase {
  57. private static final Key<String> key2 = Key.get(String.class, named("2"));
  58. private static final Key<String> key3 = Key.get(String.class, named("3"));
  59. private static final Module EMPTY_MODULE = new Module() {
  60. public void configure(Binder binder) {}
  61. };
  62. public void testOverride() {
  63. Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B")));
  64. assertEquals("B", injector.getInstance(String.class));
  65. }
  66. public void testOverrideMultiple() {
  67. Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f))
  68. .with(newModule("B"), newModule(2), newModule(1.5d));
  69. Injector injector = createInjector(module);
  70. assertEquals("B", injector.getInstance(String.class));
  71. assertEquals(2, injector.getInstance(Integer.class).intValue());
  72. assertEquals(0.5f, injector.getInstance(Float.class));
  73. assertEquals(1.5d, injector.getInstance(Double.class));
  74. }
  75. public void testOverrideUnmatchedTolerated() {
  76. Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B")));
  77. assertEquals("B", injector.getInstance(String.class));
  78. }
  79. public void testOverrideConstant() {
  80. Module original = new AbstractModule() {
  81. @Override protected void configure() {
  82. bindConstant().annotatedWith(named("Test")).to("A");
  83. }
  84. };
  85. Module replacements = new AbstractModule() {
  86. @Override protected void configure() {
  87. bindConstant().annotatedWith(named("Test")).to("B");
  88. }
  89. };
  90. Injector injector = createInjector(Modules.override(original).with(replacements));
  91. assertEquals("B", injector.getInstance(Key.get(String.class, named("Test"))));
  92. }
  93. public void testGetProviderInModule() {
  94. Module original = new AbstractModule() {
  95. @Override protected void configure() {
  96. bind(String.class).toInstance("A");
  97. bind(key2).toProvider(getProvider(String.class));
  98. }
  99. };
  100. Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE));
  101. assertEquals("A", injector.getInstance(String.class));
  102. assertEquals("A", injector.getInstance(key2));
  103. }
  104. public void testOverrideWhatGetProviderProvided() {
  105. Module original = new AbstractModule() {
  106. @Override protected void configure() {
  107. bind(String.class).toInstance("A");
  108. bind(key2).toProvider(getProvider(String.class));
  109. }
  110. };
  111. Module replacements = newModule("B");
  112. Injector injector = createInjector(Modules.override(original).with(replacements));
  113. assertEquals("B", injector.getInstance(String.class));
  114. assertEquals("B", injector.getInstance(key2));
  115. }
  116. public void testOverrideUsingOriginalsGetProvider() {
  117. Module original = new AbstractModule() {
  118. @Override protected void configure() {
  119. bind(String.class).toInstance("A");
  120. bind(key2).toInstance("B");
  121. }
  122. };
  123. Module replacements = new AbstractModule() {
  124. @Override protected void configure() {
  125. bind(String.class).toProvider(getProvider(key2));
  126. }
  127. };
  128. Injector injector = createInjector(Modules.override(original).with(replacements));
  129. assertEquals("B", injector.getInstance(String.class));
  130. assertEquals("B", injector.getInstance(key2));
  131. }
  132. public void testOverrideOfOverride() {
  133. Module original = new AbstractModule() {
  134. @Override protected void configure() {
  135. bind(String.class).toInstance("A1");
  136. bind(key2).toInstance("A2");
  137. bind(key3).toInstance("A3");
  138. }
  139. };
  140. Module replacements1 = new AbstractModule() {
  141. @Override protected void configure() {
  142. bind(String.class).toInstance("B1");
  143. bind(key2).toInstance("B2");
  144. }
  145. };
  146. Module overrides = Modules.override(original).with(replacements1);
  147. Module replacements2 = new AbstractModule() {
  148. @Override protected void configure() {
  149. bind(String.class).toInstance("C1");
  150. bind(key3).toInstance("C3");
  151. }
  152. };
  153. Injector injector = createInjector(Modules.override(overrides).with(replacements2));
  154. assertEquals("C1", injector.getInstance(String.class));
  155. assertEquals("B2", injector.getInstance(key2));
  156. assertEquals("C3", injector.getInstance(key3));
  157. }
  158. static class OuterReplacementsModule extends AbstractModule {
  159. @Override protected void configure() {
  160. install(new InnerReplacementsModule());
  161. }
  162. }
  163. static class InnerReplacementsModule extends AbstractModule {
  164. @Override protected void configure() {
  165. bind(String.class).toInstance("B");
  166. bind(String.class).toInstance("C");
  167. }
  168. }
  169. public void testOverridesTwiceFails() {
  170. Module original = newModule("A");
  171. Module replacements = new OuterReplacementsModule();
  172. Module module = Modules.override(original).with(replacements);
  173. try {
  174. createInjector(module);
  175. fail();
  176. } catch (CreationException expected) {
  177. assertContains(expected.getMessage(),
  178. "A binding to java.lang.String was already configured at "
  179. + InnerReplacementsModule.class.getName(),
  180. asModuleChain(Modules.OverrideModule.class,
  181. OuterReplacementsModule.class, InnerReplacementsModule.class),
  182. "at " + InnerReplacementsModule.class.getName(),
  183. asModuleChain(Modules.OverrideModule.class,
  184. OuterReplacementsModule.class, InnerReplacementsModule.class));
  185. }
  186. }
  187. public void testOverridesDoesntFixTwiceBoundInOriginal() {
  188. Module original = new AbstractModule() {
  189. @Override protected void configure() {
  190. bind(String.class).toInstance("A");
  191. bind(String.class).toInstance("B");
  192. }
  193. };
  194. Module replacements = new AbstractModule() {
  195. @Override protected void configure() {
  196. bind(String.class).toInstance("C");
  197. }
  198. };
  199. Module module = Modules.override(original).with(replacements);
  200. try {
  201. createInjector(module);
  202. fail();
  203. } catch (CreationException expected) {
  204. // The replacement comes first because we replace A with C,
  205. // then we encounter B and freak out.
  206. assertContains(expected.getMessage(),
  207. "1) A binding to java.lang.String was already configured at "
  208. + replacements.getClass().getName(),
  209. asModuleChain(Modules.OverrideModule.class, replacements.getClass()),
  210. "at " + original.getClass().getName(),
  211. asModuleChain(Modules.OverrideModule.class, original.getClass()));
  212. }
  213. }
  214. public void testStandardScopeAnnotation() {
  215. final SingleUseScope scope = new SingleUseScope();
  216. Module module = new AbstractModule() {
  217. @Override protected void configure() {
  218. bindScope(TestScopeAnnotation.class, scope);
  219. bind(String.class).in(TestScopeAnnotation.class);
  220. }
  221. };
  222. assertFalse(scope.used);
  223. Guice.createInjector(module);
  224. assertTrue(scope.used);
  225. }
  226. public void testOverrideUntargettedBinding() {
  227. Module original = new AbstractModule() {
  228. @Override protected void configure() {
  229. bind(Date.class);
  230. }
  231. };
  232. Module replacements = new AbstractModule() {
  233. @Override protected void configure() {
  234. bind(Date.class).toInstance(new Date(0));
  235. }
  236. };
  237. Injector injector = createInjector(Modules.override(original).with(replacements));
  238. assertEquals(0, injector.getInstance(Date.class).getTime());
  239. }
  240. public void testOverrideScopeAnnotation() {
  241. final Scope scope = new Scope() {
  242. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  243. throw new AssertionError("Should not be called");
  244. }
  245. };
  246. final SingleUseScope replacementScope = new SingleUseScope();
  247. Module original = new AbstractModule() {
  248. @Override protected void configure() {
  249. bindScope(TestScopeAnnotation.class, scope);
  250. bind(Date.class).in(TestScopeAnnotation.class);
  251. }
  252. };
  253. Module replacements = new AbstractModule() {
  254. @Override protected void configure() {
  255. bindScope(TestScopeAnnotation.class, replacementScope);
  256. }
  257. };
  258. Injector injector = createInjector(Modules.override(original).with(replacements));
  259. injector.getInstance(Date.class);
  260. assertTrue(replacementScope.used);
  261. }
  262. public void testFailsIfOverridenScopeInstanceHasBeenUsed() {
  263. final Scope scope = new Scope() {
  264. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  265. return unscoped;
  266. }
  267. @Override public String toString() {
  268. return "ORIGINAL SCOPE";
  269. }
  270. };
  271. final Module original = new AbstractModule() {
  272. @Override protected void configure() {
  273. bindScope(TestScopeAnnotation.class, scope);
  274. bind(Date.class).in(scope);
  275. bind(String.class).in(scope);
  276. }
  277. };
  278. Module originalWrapper = new AbstractModule() {
  279. @Override protected void configure() {
  280. install(original);
  281. }
  282. };
  283. Module replacements = new AbstractModule() {
  284. @Override protected void configure() {
  285. bindScope(TestScopeAnnotation.class, new SingleUseScope());
  286. }
  287. };
  288. try {
  289. createInjector(Modules.override(originalWrapper).with(replacements));
  290. fail("Exception expected");
  291. } catch (CreationException e) {
  292. assertContains(e.getMessage(),
  293. "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.",
  294. "original binding at " + original.getClass().getName() + ".configure(",
  295. asModuleChain(originalWrapper.getClass(), original.getClass()),
  296. "bound directly at " + original.getClass().getName() + ".configure(",
  297. asModuleChain(originalWrapper.getClass(), original.getClass()),
  298. "bound directly at " + original.getClass().getName() + ".configure(",
  299. asModuleChain(originalWrapper.getClass(), original.getClass()),
  300. "at ", replacements.getClass().getName() + ".configure(",
  301. asModuleChain(Modules.OverrideModule.class, replacements.getClass()));
  302. }
  303. }
  304. public void testOverrideIsLazy() {
  305. final AtomicReference<String> value = new AtomicReference<String>("A");
  306. Module overridden = Modules.override(new AbstractModule() {
  307. @Override protected void configure() {
  308. bind(String.class).annotatedWith(named("original")).toInstance(value.get());
  309. }
  310. }).with(new AbstractModule() {
  311. @Override protected void configure() {
  312. bind(String.class).annotatedWith(named("override")).toInstance(value.get());
  313. }
  314. });
  315. // the value.get() call should be deferred until Guice.createInjector
  316. value.set("B");
  317. Injector injector = Guice.createInjector(overridden);
  318. assertEquals("B", injector.getInstance(Key.get(String.class, named("original"))));
  319. assertEquals("B", injector.getInstance(Key.get(String.class, named("override"))));
  320. }
  321. public void testOverridePrivateModuleOverPrivateModule() {
  322. Module exposes5and6 = new AbstractModule() {
  323. @Override protected void configure() {
  324. install(new PrivateModule() {
  325. @Override protected void configure() {
  326. bind(Integer.class).toInstance(5);
  327. expose(Integer.class);
  328. bind(Character.class).toInstance('E');
  329. }
  330. });
  331. install(new PrivateModule() {
  332. @Override protected void configure() {
  333. bind(Long.class).toInstance(6L);
  334. expose(Long.class);
  335. bind(Character.class).toInstance('F');
  336. }
  337. });
  338. }
  339. };
  340. AbstractModule exposes15 = new AbstractModule() {
  341. @Override protected void configure() {
  342. install(new PrivateModule() {
  343. @Override protected void configure() {
  344. bind(Integer.class).toInstance(15);
  345. expose(Integer.class);
  346. bind(Character.class).toInstance('G');
  347. }
  348. });
  349. install(new PrivateModule() {
  350. @Override protected void configure() {
  351. bind(Character.class).toInstance('H');
  352. }
  353. });
  354. }
  355. };
  356. // override forwards
  357. Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15));
  358. assertEquals(15, injector.getInstance(Integer.class).intValue());
  359. assertEquals(6L, injector.getInstance(Long.class).longValue());
  360. // and in reverse order
  361. Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6));
  362. assertEquals(5, reverse.getInstance(Integer.class).intValue());
  363. assertEquals(6L, reverse.getInstance(Long.class).longValue());
  364. }
  365. public void testOverrideModuleAndPrivateModule() {
  366. Module exposes5 = new PrivateModule() {
  367. @Override protected void configure() {
  368. bind(Integer.class).toInstance(5);
  369. expose(Integer.class);
  370. }
  371. };
  372. Module binds15 = new AbstractModule() {
  373. @Override protected void configure() {
  374. bind(Integer.class).toInstance(15);
  375. }
  376. };
  377. Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
  378. assertEquals(15, injector.getInstance(Integer.class).intValue());
  379. Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5));
  380. assertEquals(5, reverse.getInstance(Integer.class).intValue());
  381. }
  382. public void testOverrideDeepExpose() {
  383. final AtomicReference<Provider<Character>> charAProvider
  384. = new AtomicReference<Provider<Character>>();
  385. Module exposes5 = new PrivateModule() {
  386. @Override protected void configure() {
  387. install(new PrivateModule() {
  388. @Override protected void configure() {
  389. bind(Integer.class).toInstance(5);
  390. expose(Integer.class);
  391. charAProvider.set(getProvider(Character.class));
  392. bind(Character.class).toInstance('A');
  393. }
  394. });
  395. expose(Integer.class);
  396. }
  397. };
  398. Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE));
  399. assertEquals(5, injector.getInstance(Integer.class).intValue());
  400. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  401. injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5));
  402. assertEquals(5, injector.getInstance(Integer.class).intValue());
  403. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  404. final AtomicReference<Provider<Character>> charBProvider
  405. = new AtomicReference<Provider<Character>>();
  406. Module binds15 = new AbstractModule() {
  407. @Override protected void configure() {
  408. bind(Integer.class).toInstance(15);
  409. install(new PrivateModule() {
  410. @Override protected void configure() {
  411. charBProvider.set(getProvider(Character.class));
  412. bind(Character.class).toInstance('B');
  413. }
  414. });
  415. }
  416. };
  417. injector = Guice.createInjector(Modules.override(binds15).with(exposes5));
  418. assertEquals(5, injector.getInstance(Integer.class).intValue());
  419. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  420. assertEquals('B', charBProvider.getAndSet(null).get().charValue());
  421. injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
  422. assertEquals(15, injector.getInstance(Integer.class).intValue());
  423. assertEquals('A', charAProvider.getAndSet(null).get().charValue());
  424. assertEquals('B', charBProvider.getAndSet(null).get().charValue());
  425. }
  426. @Retention(RUNTIME)
  427. @Target(TYPE)
  428. @ScopeAnnotation
  429. private static @interface TestScopeAnnotation {}
  430. private static class SingleUseScope implements Scope {
  431. boolean used = false;
  432. public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
  433. assertFalse(used);
  434. used = true;
  435. return unscoped;
  436. }
  437. }
  438. static class NewModule<T> extends AbstractModule {
  439. private final T bound;
  440. NewModule(T bound) {
  441. this.bound = bound;
  442. }
  443. @Override protected void configure() {
  444. @SuppressWarnings("unchecked")
  445. Class<T> type = (Class<T>)bound.getClass();
  446. bind(type).toInstance(bound);
  447. }
  448. }
  449. private static <T> Module newModule(final T bound) {
  450. return new NewModule<T>(bound);
  451. }
  452. private static final String RESULT = "RESULT";
  453. private static final String PRIVATE_INPUT = "PRIVATE_INPUT";
  454. private static final String OVERRIDDEN_INPUT = "FOO";
  455. private static final String OVERRIDDEN_RESULT = "Size: 3";
  456. private static final Key<String> RESULT_KEY = Key.get(String.class, named(RESULT));
  457. private static final Key<String> INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT));
  458. public void testExposedBindingOverride() throws Exception {
  459. Injector inj = Guice.createInjector(
  460. Modules.override(new ExampleModule()).with(
  461. new AbstractModule() {
  462. @Override protected void configure() {
  463. bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT);
  464. }
  465. }));
  466. assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  467. }
  468. public void testPrivateBindingOverride() throws Exception {
  469. Injector inj = Guice.createInjector(
  470. Modules.override(new ExampleModule()).with(
  471. new AbstractModule() {
  472. @Override protected void configure() {
  473. bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT);
  474. }
  475. }));
  476. assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  477. }
  478. public static class ExampleModule extends PrivateModule {
  479. @Provides @Exposed @Named(RESULT)
  480. public String provideResult(@Named(PRIVATE_INPUT) String input) {
  481. return "Size: " + input.length();
  482. }
  483. @Provides @Named(PRIVATE_INPUT)
  484. public String provideInput() {
  485. return "Hello World";
  486. }
  487. @Override protected void configure() {
  488. }
  489. }
  490. public void testEqualsNotCalledByDefaultOnInstance() {
  491. final HashEqualsTester a = new HashEqualsTester();
  492. a.throwOnEquals = true;
  493. Guice.createInjector(Modules.override(new AbstractModule() {
  494. @Override
  495. protected void configure() {
  496. bind(String.class);
  497. bind(HashEqualsTester.class).toInstance(a);
  498. }
  499. }).with());
  500. }
  501. public void testEqualsNotCalledByDefaultOnProvider() {
  502. final HashEqualsTester a = new HashEqualsTester();
  503. a.throwOnEquals = true;
  504. Guice.createInjector(Modules.override(new AbstractModule() {
  505. @Override
  506. protected void configure() {
  507. bind(String.class);
  508. bind(Object.class).toProvider(a);
  509. }
  510. }).with());
  511. }
  512. public void testHashcodeNeverCalledOnInstance() {
  513. final HashEqualsTester a = new HashEqualsTester();
  514. a.throwOnHashcode = true;
  515. a.equality = "test";
  516. final HashEqualsTester b = new HashEqualsTester();
  517. b.throwOnHashcode = true;
  518. b.equality = "test";
  519. Guice.createInjector(Modules.override(new AbstractModule() {
  520. @Override
  521. protected void configure() {
  522. bind(String.class);
  523. bind(HashEqualsTester.class).toInstance(a);
  524. bind(HashEqualsTester.class).toInstance(b);
  525. }
  526. }).with());
  527. }
  528. public void testHashcodeNeverCalledOnProviderInstance() {
  529. final HashEqualsTester a = new HashEqualsTester();
  530. a.throwOnHashcode = true;
  531. a.equality = "test";
  532. final HashEqualsTester b = new HashEqualsTester();
  533. b.throwOnHashcode = true;
  534. b.equality = "test";
  535. Guice.createInjector(Modules.override(new AbstractModule() {
  536. @Override
  537. protected void configure() {
  538. bind(String.class);
  539. bind(Object.class).toProvider(a);
  540. bind(Object.class).toProvider(b);
  541. }
  542. }).with());
  543. }
  544. private static class HashEqualsTester implements Provider<Object> {
  545. private String equality;
  546. private boolean throwOnEquals;
  547. private boolean throwOnHashcode;
  548. @Override
  549. public boolean equals(Object obj) {
  550. if (throwOnEquals) {
  551. throw new RuntimeException();
  552. } else if (obj instanceof HashEqualsTester) {
  553. HashEqualsTester o = (HashEqualsTester)obj;
  554. if(o.throwOnEquals) {
  555. throw new RuntimeException();
  556. }
  557. if(equality == null && o.equality == null) {
  558. return this == o;
  559. } else {
  560. return Objects.equal(equality, o.equality);
  561. }
  562. } else {
  563. return false;
  564. }
  565. }
  566. @Override
  567. public int hashCode() {
  568. if(throwOnHashcode) {
  569. throw new RuntimeException();
  570. } else {
  571. return super.hashCode();
  572. }
  573. }
  574. public Object get() {
  575. return new Object();
  576. }
  577. }
  578. public void testCorrectStage() {
  579. final Stage stage = Stage.PRODUCTION;
  580. Module module = Modules.override(new AbstractModule() {
  581. @Override
  582. protected void configure() {
  583. if (currentStage() != Stage.PRODUCTION) {
  584. addError("Wronge stage in overridden module:" + currentStage());
  585. }
  586. }
  587. }).with(new AbstractModule() {
  588. @Override
  589. protected void configure() {
  590. if (currentStage() != Stage.PRODUCTION) {
  591. addError("Wronge stage in overriding module:" + currentStage());
  592. }
  593. }
  594. });
  595. Guice.createInjector(stage, module);
  596. }
  597. public void testOverridesApplyOriginalScanners() {
  598. Injector injector =
  599. Guice.createInjector(Modules.override(NamedMunger.module()).with(new AbstractModule() {
  600. @Override protected void configure() {}
  601. @TestProvides @Named("test") String provideString() { return "foo"; }
  602. }));
  603. assertNull(injector.getExistingBinding(Key.get(String.class, named("test"))));
  604. Binding<String> binding = injector.getBinding(Key.get(String.class, named("test-munged")));
  605. assertEquals("foo", binding.getProvider().get());
  606. }
  607. @Documented @Target(METHOD) @Retention(RUNTIME)
  608. private @interface TestProvides {}
  609. private static class NamedMunger extends ModuleAnnotatedMethodScanner {
  610. static Module module() {
  611. return new AbstractModule() {
  612. @Override protected void configure() {
  613. binder().scanModulesForAnnotatedMethods(new NamedMunger());
  614. }
  615. };
  616. }
  617. @Override
  618. public String toString() {
  619. return "NamedMunger";
  620. }
  621. @Override
  622. public Set<? extends Class<? extends Annotation>> annotationClasses() {
  623. return ImmutableSet.of(TestProvides.class);
  624. }
  625. @Override
  626. public <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
  627. InjectionPoint injectionPoint) {
  628. return Key.get(key.getTypeLiteral(),
  629. Names.named(((Named) key.getAnnotation()).value() + "-munged"));
  630. }
  631. }
  632. }