/* * Copyright (C) 2006 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; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.inject.util.Modules; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.TestCase; /** @author crazybob@google.com (Bob Lee) */ public class GenericInjectionTest extends TestCase { public void testGenericInjection() throws CreationException { final List names = Arrays.asList("foo", "bar", "bob"); Injector injector = Guice.createInjector( (Module) new AbstractModule() { @Override protected void configure() { bind(new TypeLiteral>() {}).toInstance(names); } }); Foo foo = injector.getInstance(Foo.class); assertEquals(names, foo.names); } static class Foo { @Inject List names; } /** * Although we may not have intended to support this behaviour, this test passes under Guice 1.0. * The workaround is to add an explicit binding for the parameterized type. See {@link * #testExplicitBindingOfGenericType()}. */ public void testImplicitBindingOfGenericType() { Parameterized parameterized = Guice.createInjector().getInstance(Key.get(new TypeLiteral>() {})); assertNotNull(parameterized); } public void testExplicitBindingOfGenericType() { Injector injector = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bind(Key.get(new TypeLiteral>() {})) .to((Class) Parameterized.class); } }); Parameterized parameterized = injector.getInstance(Key.get(new TypeLiteral>() {})); assertNotNull(parameterized); } static class Parameterized { @Inject Parameterized() {} } public void testInjectingParameterizedDependenciesForImplicitBinding() { assertParameterizedDepsInjected( new Key>() {}, Modules.EMPTY_MODULE); } public void testInjectingParameterizedDependenciesForBindingTarget() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected( Key.get(Object.class), new AbstractModule() { @Override protected void configure() { bind(Object.class).to(type); } }); } public void testInjectingParameterizedDependenciesForBindingSource() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected( Key.get(type), new AbstractModule() { @Override protected void configure() { bind(type); } }); } public void testBindingToSubtype() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected( Key.get(type), new AbstractModule() { @Override protected void configure() { bind(type).to(new TypeLiteral>() {}); } }); } public void testBindingSubtype() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected( Key.get(type), new AbstractModule() { @Override protected void configure() { bind(type); } }); } @SuppressWarnings("unchecked") public void assertParameterizedDepsInjected(Key key, Module bindingModule) { Module bindDataModule = new AbstractModule() { @Provides Map provideMap() { return ImmutableMap.of("one", 1, "two", 2); } @Provides Set provideSet(Map map) { return map.keySet(); } @Provides Collection provideCollection(Map map) { return map.values(); } }; Injector injector = Guice.createInjector(bindDataModule, bindingModule); ParameterizedDeps parameterizedDeps = (ParameterizedDeps) injector.getInstance(key); assertEquals(ImmutableMap.of("one", 1, "two", 2), parameterizedDeps.map); assertEquals(ImmutableSet.of("one", "two"), parameterizedDeps.keys); assertEquals(ImmutableSet.of(1, 2), ImmutableSet.copyOf(parameterizedDeps.values)); } static class SubParameterizedDeps extends ParameterizedDeps { @Inject SubParameterizedDeps(Set keys) { super(keys); } } static class ParameterizedDeps { @Inject private Map map; private Set keys; private Collection values; @Inject ParameterizedDeps(Set keys) { this.keys = keys; } @Inject void method(Collection values) { this.values = values; } } public void testImmediateTypeVariablesAreInjected() { Injector injector = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("tee"); } }); InjectsT injectsT = injector.getInstance(new Key>() {}); assertEquals("tee", injectsT.t); } static class InjectsT { @Inject T t; } }