• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.inject;
18 
19 import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.ImmutableSet;
21 import com.google.inject.util.Modules;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import junit.framework.TestCase;
28 
29 /** @author crazybob@google.com (Bob Lee) */
30 public class GenericInjectionTest extends TestCase {
31 
testGenericInjection()32   public void testGenericInjection() throws CreationException {
33     final List<String> names = Arrays.asList("foo", "bar", "bob");
34 
35     Injector injector =
36         Guice.createInjector(
37             (Module)
38                 new AbstractModule() {
39                   @Override
40                   protected void configure() {
41                     bind(new TypeLiteral<List<String>>() {}).toInstance(names);
42                   }
43                 });
44 
45     Foo foo = injector.getInstance(Foo.class);
46     assertEquals(names, foo.names);
47   }
48 
49   static class Foo {
50     @Inject List<String> names;
51   }
52 
53   /**
54    * Although we may not have intended to support this behaviour, this test passes under Guice 1.0.
55    * The workaround is to add an explicit binding for the parameterized type. See {@link
56    * #testExplicitBindingOfGenericType()}.
57    */
testImplicitBindingOfGenericType()58   public void testImplicitBindingOfGenericType() {
59     Parameterized<String> parameterized =
60         Guice.createInjector().getInstance(Key.get(new TypeLiteral<Parameterized<String>>() {}));
61     assertNotNull(parameterized);
62   }
63 
testExplicitBindingOfGenericType()64   public void testExplicitBindingOfGenericType() {
65     Injector injector =
66         Guice.createInjector(
67             new AbstractModule() {
68               @Override
69               protected void configure() {
70                 bind(Key.get(new TypeLiteral<Parameterized<String>>() {}))
71                     .to((Class) Parameterized.class);
72               }
73             });
74 
75     Parameterized<String> parameterized =
76         injector.getInstance(Key.get(new TypeLiteral<Parameterized<String>>() {}));
77     assertNotNull(parameterized);
78   }
79 
80   static class Parameterized<T> {
81     @Inject
Parameterized()82     Parameterized() {}
83   }
84 
testInjectingParameterizedDependenciesForImplicitBinding()85   public void testInjectingParameterizedDependenciesForImplicitBinding() {
86     assertParameterizedDepsInjected(
87         new Key<ParameterizedDeps<String, Integer>>() {}, Modules.EMPTY_MODULE);
88   }
89 
testInjectingParameterizedDependenciesForBindingTarget()90   public void testInjectingParameterizedDependenciesForBindingTarget() {
91     final TypeLiteral<ParameterizedDeps<String, Integer>> type =
92         new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
93 
94     assertParameterizedDepsInjected(
95         Key.get(Object.class),
96         new AbstractModule() {
97           @Override
98           protected void configure() {
99             bind(Object.class).to(type);
100           }
101         });
102   }
103 
testInjectingParameterizedDependenciesForBindingSource()104   public void testInjectingParameterizedDependenciesForBindingSource() {
105     final TypeLiteral<ParameterizedDeps<String, Integer>> type =
106         new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
107 
108     assertParameterizedDepsInjected(
109         Key.get(type),
110         new AbstractModule() {
111           @Override
112           protected void configure() {
113             bind(type);
114           }
115         });
116   }
117 
testBindingToSubtype()118   public void testBindingToSubtype() {
119     final TypeLiteral<ParameterizedDeps<String, Integer>> type =
120         new TypeLiteral<ParameterizedDeps<String, Integer>>() {};
121 
122     assertParameterizedDepsInjected(
123         Key.get(type),
124         new AbstractModule() {
125           @Override
126           protected void configure() {
127             bind(type).to(new TypeLiteral<SubParameterizedDeps<String, Long, Integer>>() {});
128           }
129         });
130   }
131 
testBindingSubtype()132   public void testBindingSubtype() {
133     final TypeLiteral<SubParameterizedDeps<String, Long, Integer>> type =
134         new TypeLiteral<SubParameterizedDeps<String, Long, Integer>>() {};
135 
136     assertParameterizedDepsInjected(
137         Key.get(type),
138         new AbstractModule() {
139           @Override
140           protected void configure() {
141             bind(type);
142           }
143         });
144   }
145 
146   @SuppressWarnings("unchecked")
assertParameterizedDepsInjected(Key<?> key, Module bindingModule)147   public void assertParameterizedDepsInjected(Key<?> key, Module bindingModule) {
148     Module bindDataModule =
149         new AbstractModule() {
150 
151           @Provides
152           Map<String, Integer> provideMap() {
153             return ImmutableMap.of("one", 1, "two", 2);
154           }
155 
156           @Provides
157           Set<String> provideSet(Map<String, Integer> map) {
158             return map.keySet();
159           }
160 
161           @Provides
162           Collection<Integer> provideCollection(Map<String, Integer> map) {
163             return map.values();
164           }
165         };
166 
167     Injector injector = Guice.createInjector(bindDataModule, bindingModule);
168     ParameterizedDeps<String, Integer> parameterizedDeps =
169         (ParameterizedDeps<String, Integer>) injector.getInstance(key);
170     assertEquals(ImmutableMap.of("one", 1, "two", 2), parameterizedDeps.map);
171     assertEquals(ImmutableSet.of("one", "two"), parameterizedDeps.keys);
172     assertEquals(ImmutableSet.of(1, 2), ImmutableSet.copyOf(parameterizedDeps.values));
173   }
174 
175   static class SubParameterizedDeps<A, B, C> extends ParameterizedDeps<A, C> {
176     @Inject
SubParameterizedDeps(Set<A> keys)177     SubParameterizedDeps(Set<A> keys) {
178       super(keys);
179     }
180   }
181 
182   static class ParameterizedDeps<K, V> {
183     @Inject private Map<K, V> map;
184     private Set<K> keys;
185     private Collection<V> values;
186 
187     @Inject
ParameterizedDeps(Set<K> keys)188     ParameterizedDeps(Set<K> keys) {
189       this.keys = keys;
190     }
191 
192     @Inject
method(Collection<V> values)193     void method(Collection<V> values) {
194       this.values = values;
195     }
196   }
197 
testImmediateTypeVariablesAreInjected()198   public void testImmediateTypeVariablesAreInjected() {
199     Injector injector =
200         Guice.createInjector(
201             new AbstractModule() {
202               @Override
203               protected void configure() {
204                 bind(String.class).toInstance("tee");
205               }
206             });
207     InjectsT<String> injectsT = injector.getInstance(new Key<InjectsT<String>>() {});
208     assertEquals("tee", injectsT.t);
209   }
210 
211   static class InjectsT<T> {
212     @Inject T t;
213   }
214 }
215