/extensions/multibindings/test/com/google/inject/multibindings/ProvidesIntoTest.java
Java | 373 lines | 298 code | 55 blank | 20 comment | 2 complexity | e40e15868bd759d67810995fe6d4460f MD5 | raw file
- /**
- * Copyright (C) 2015 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.google.inject.multibindings;
- import static com.google.inject.Asserts.assertContains;
- import static com.google.inject.name.Names.named;
- import static java.lang.annotation.RetentionPolicy.RUNTIME;
- import com.google.common.base.Optional;
- import com.google.common.collect.ImmutableMap;
- import com.google.common.collect.ImmutableSet;
- import com.google.inject.AbstractModule;
- import com.google.inject.CreationException;
- import com.google.inject.Guice;
- import com.google.inject.Injector;
- import com.google.inject.Key;
- import com.google.inject.Module;
- import com.google.inject.multibindings.ProvidesIntoOptional.Type;
- import com.google.inject.name.Named;
- import junit.framework.TestCase;
- import java.lang.annotation.Retention;
- import java.lang.reflect.Field;
- import java.util.Map;
- import java.util.Set;
- /**
- * Tests the various @ProvidesInto annotations.
- *
- * @author sameb@google.com (Sam Berlin)
- */
- public class ProvidesIntoTest extends TestCase {
- public void testAnnotation() throws Exception {
- Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoSet
- @Named("foo")
- String setFoo() { return "foo"; }
- @ProvidesIntoSet
- @Named("foo")
- String setFoo2() { return "foo2"; }
- @ProvidesIntoSet
- @Named("bar")
- String setBar() { return "bar"; }
- @ProvidesIntoSet
- @Named("bar")
- String setBar2() { return "bar2"; }
- @ProvidesIntoSet
- String setNoAnnotation() { return "na"; }
- @ProvidesIntoSet
- String setNoAnnotation2() { return "na2"; }
- @ProvidesIntoMap
- @StringMapKey("fooKey")
- @Named("foo")
- String mapFoo() { return "foo"; }
- @ProvidesIntoMap
- @StringMapKey("foo2Key")
- @Named("foo")
- String mapFoo2() { return "foo2"; }
- @ProvidesIntoMap
- @ClassMapKey(String.class)
- @Named("bar")
- String mapBar() { return "bar"; }
- @ProvidesIntoMap
- @ClassMapKey(Number.class)
- @Named("bar")
- String mapBar2() { return "bar2"; }
- @ProvidesIntoMap
- @TestEnumKey(TestEnum.A)
- String mapNoAnnotation() { return "na"; }
- @ProvidesIntoMap
- @TestEnumKey(TestEnum.B)
- String mapNoAnnotation2() { return "na2"; }
- @ProvidesIntoMap
- @WrappedKey(number = 1)
- Number wrapped1() { return 11; }
- @ProvidesIntoMap
- @WrappedKey(number = 2)
- Number wrapped2() { return 22; }
- @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT)
- @Named("foo")
- String optionalDefaultFoo() { return "foo"; }
- @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL)
- @Named("foo")
- String optionalActualFoo() { return "foo2"; }
- @ProvidesIntoOptional(ProvidesIntoOptional.Type.DEFAULT)
- @Named("bar")
- String optionalDefaultBar() { return "bar"; }
- @ProvidesIntoOptional(ProvidesIntoOptional.Type.ACTUAL)
- String optionalActualBar() { return "na2"; }
- });
- Set<String> fooSet = injector.getInstance(new Key<Set<String>>(named("foo")) {});
- assertEquals(ImmutableSet.of("foo", "foo2"), fooSet);
- Set<String> barSet = injector.getInstance(new Key<Set<String>>(named("bar")) {});
- assertEquals(ImmutableSet.of("bar", "bar2"), barSet);
- Set<String> noAnnotationSet = injector.getInstance(new Key<Set<String>>() {});
- assertEquals(ImmutableSet.of("na", "na2"), noAnnotationSet);
- Map<String, String> fooMap =
- injector.getInstance(new Key<Map<String, String>>(named("foo")) {});
- assertEquals(ImmutableMap.of("fooKey", "foo", "foo2Key", "foo2"), fooMap);
- Map<Class<?>, String> barMap =
- injector.getInstance(new Key<Map<Class<?>, String>>(named("bar")) {});
- assertEquals(ImmutableMap.of(String.class, "bar", Number.class, "bar2"), barMap);
- Map<TestEnum, String> noAnnotationMap =
- injector.getInstance(new Key<Map<TestEnum, String>>() {});
- assertEquals(ImmutableMap.of(TestEnum.A, "na", TestEnum.B, "na2"), noAnnotationMap);
- Map<WrappedKey, Number> wrappedMap =
- injector.getInstance(new Key<Map<WrappedKey, Number>>() {});
- assertEquals(ImmutableMap.of(wrappedKeyFor(1), 11, wrappedKeyFor(2), 22), wrappedMap);
- Optional<String> fooOptional =
- injector.getInstance(new Key<Optional<String>>(named("foo")) {});
- assertEquals("foo2", fooOptional.get());
- Optional<String> barOptional =
- injector.getInstance(new Key<Optional<String>>(named("bar")) {});
- assertEquals("bar", barOptional.get());
- Optional<String> noAnnotationOptional =
- injector.getInstance(new Key<Optional<String>>() {});
- assertEquals("na2", noAnnotationOptional.get());
- }
- enum TestEnum {
- A, B
- }
- @MapKey(unwrapValue = true)
- @Retention(RUNTIME)
- @interface TestEnumKey {
- TestEnum value();
- }
- @MapKey(unwrapValue = false)
- @Retention(RUNTIME)
- @interface WrappedKey {
- int number();
- }
-
- @SuppressWarnings("unused") @WrappedKey(number=1) private static Object wrappedKey1Holder;
- @SuppressWarnings("unused") @WrappedKey(number=2) private static Object wrappedKey2Holder;
- WrappedKey wrappedKeyFor(int number) throws Exception {
- Field field;
- switch (number) {
- case 1:
- field = ProvidesIntoTest.class.getDeclaredField("wrappedKey1Holder");
- break;
- case 2:
- field = ProvidesIntoTest.class.getDeclaredField("wrappedKey2Holder");
- break;
- default:
- throw new IllegalArgumentException("only 1 or 2 supported");
- }
- return field.getAnnotation(WrappedKey.class);
- }
-
- public void testDoubleScannerIsIgnored() {
- Injector injector = Guice.createInjector(
- MultibindingsScanner.asModule(),
- MultibindingsScanner.asModule(),
- new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoSet String provideFoo() { return "foo"; }
- }
- );
- assertEquals(ImmutableSet.of("foo"), injector.getInstance(new Key<Set<String>>() {}));
- }
-
- @MapKey(unwrapValue = true)
- @Retention(RUNTIME)
- @interface ArrayUnwrappedKey {
- int[] value();
- }
-
- public void testArrayKeys_unwrapValuesTrue() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoMap @ArrayUnwrappedKey({1, 2}) String provideFoo() { return "foo"; }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(),
- "Array types are not allowed in a MapKey with unwrapValue=true: "
- + ArrayUnwrappedKey.class.getName(),
- "at " + m.getClass().getName() + ".provideFoo(");
- }
- }
- @MapKey(unwrapValue = false)
- @Retention(RUNTIME)
- @interface ArrayWrappedKey {
- int[] number();
- }
-
- @SuppressWarnings("unused") @ArrayWrappedKey(number={1, 2}) private static Object arrayWrappedKeyHolder12;
- @SuppressWarnings("unused") @ArrayWrappedKey(number={3, 4}) private static Object arrayWrappedKeyHolder34;
- ArrayWrappedKey arrayWrappedKeyFor(int number) throws Exception {
- Field field;
- switch (number) {
- case 12:
- field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder12");
- break;
- case 34:
- field = ProvidesIntoTest.class.getDeclaredField("arrayWrappedKeyHolder34");
- break;
- default:
- throw new IllegalArgumentException("only 1 or 2 supported");
- }
- return field.getAnnotation(ArrayWrappedKey.class);
- }
-
- public void testArrayKeys_unwrapValuesFalse() throws Exception {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoMap @ArrayWrappedKey(number = {1, 2}) String provideFoo() { return "foo"; }
- @ProvidesIntoMap @ArrayWrappedKey(number = {3, 4}) String provideBar() { return "bar"; }
- };
- Injector injector = Guice.createInjector(MultibindingsScanner.asModule(), m);
- Map<ArrayWrappedKey, String> map =
- injector.getInstance(new Key<Map<ArrayWrappedKey, String>>() {});
- ArrayWrappedKey key12 = arrayWrappedKeyFor(12);
- ArrayWrappedKey key34 = arrayWrappedKeyFor(34);
- assertEquals("foo", map.get(key12));
- assertEquals("bar", map.get(key34));
- assertEquals(2, map.size());
- }
-
- public void testProvidesIntoSetWithMapKey() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoSet @TestEnumKey(TestEnum.A) String provideFoo() { return "foo"; }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at "
- + m.getClass().getName() + ".provideFoo");
- }
- }
-
- public void testProvidesIntoOptionalWithMapKey() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoOptional(Type.ACTUAL)
- @TestEnumKey(TestEnum.A)
- String provideFoo() {
- return "foo";
- }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(), "Found a MapKey annotation on non map binding at "
- + m.getClass().getName() + ".provideFoo");
- }
- }
-
- public void testProvidesIntoMapWithoutMapKey() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoMap String provideFoo() { return "foo"; }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(), "No MapKey found for map binding at "
- + m.getClass().getName() + ".provideFoo");
- }
- }
-
- @MapKey(unwrapValue = true)
- @Retention(RUNTIME)
- @interface TestEnumKey2 {
- TestEnum value();
- }
-
- public void testMoreThanOneMapKeyAnnotation() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoMap
- @TestEnumKey(TestEnum.A)
- @TestEnumKey2(TestEnum.B)
- String provideFoo() {
- return "foo";
- }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(), "Found more than one MapKey annotations on "
- + m.getClass().getName() + ".provideFoo");
- }
- }
-
- @MapKey(unwrapValue = true)
- @Retention(RUNTIME)
- @interface MissingValueMethod {
- }
-
- public void testMapKeyMissingValueMethod() {
- Module m = new AbstractModule() {
- @Override protected void configure() {}
- @ProvidesIntoMap
- @MissingValueMethod
- String provideFoo() {
- return "foo";
- }
- };
- try {
- Guice.createInjector(MultibindingsScanner.asModule(), m);
- fail();
- } catch (CreationException ce) {
- assertEquals(1, ce.getErrorMessages().size());
- assertContains(ce.getMessage(), "No 'value' method in MapKey with unwrapValue=true: "
- + MissingValueMethod.class.getName());
- }
- }
- }