1 /*
2  * Copyright (C) 2012 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 
18 package com.google.inject;
19 
20 import junit.framework.TestCase;
21 
22 /**
23  * Tests for {@link Binder#requireAtInjectOnConstructors()}
24  *
25  * @author sameb@google.com (Sam Berlin)
26  */
27 public class RequireAtInjectOnConstructorsTest extends TestCase {
28 
testNoCxtors_explicitBinding()29   public void testNoCxtors_explicitBinding() {
30     try {
31       Guice.createInjector(new AbstractModule() {
32         @Override
33         protected void configure() {
34           bind(NoCxtors.class);
35           binder().requireAtInjectOnConstructors();
36         }
37       });
38       fail();
39     } catch (CreationException ce) {
40       assertEquals(1, ce.getErrorMessages().size());
41       Asserts.assertContains(ce.getMessage(),
42           "1) Explicit @Inject annotations are required on constructors, but "
43           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
44           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
45     }
46   }
47 
testNoCxtors_jitBinding()48   public void testNoCxtors_jitBinding() {
49     Injector injector = Guice.createInjector(new AbstractModule() {
50       @Override
51       protected void configure() {
52         binder().requireAtInjectOnConstructors();
53       }
54     });
55     try {
56       injector.getInstance(NoCxtors.class);
57       fail();
58     } catch (ConfigurationException ce) {
59       Asserts.assertContains(ce.getMessage(),
60           "1) Explicit @Inject annotations are required on constructors, but "
61           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
62           "while locating " + NoCxtors.class.getName());
63     }
64   }
65 
testNoCxtors_implicitBinding()66   public void testNoCxtors_implicitBinding() {
67     try {
68       Guice.createInjector(new AbstractModule() {
69         @Override
70         protected void configure() {
71           bind(Interface.class).to(NoCxtors.class);
72           binder().requireAtInjectOnConstructors();
73         }
74       });
75       fail();
76     } catch (CreationException ce) {
77       assertEquals(1, ce.getErrorMessages().size());
78       Asserts.assertContains(ce.getMessage(),
79           "1) Explicit @Inject annotations are required on constructors, but "
80           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
81           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
82     }
83   }
84 
testNoCxtors_inheritedByPrivateModules()85   public void testNoCxtors_inheritedByPrivateModules() {
86     try {
87       Guice.createInjector(new AbstractModule() {
88         @Override
89         protected void configure() {
90           binder().requireAtInjectOnConstructors();
91           install(new PrivateModule() {
92             @Override
93             protected void configure() {
94               bind(NoCxtors.class);
95             }
96           });
97         }
98       });
99       fail();
100     } catch (CreationException ce) {
101       assertEquals(1, ce.getErrorMessages().size());
102       Asserts.assertContains(ce.getMessage(),
103           "1) Explicit @Inject annotations are required on constructors, but "
104           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
105           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
106     }
107   }
108 
testNoCxtors_accumulatesAllErrors()109   public void testNoCxtors_accumulatesAllErrors() {
110     try {
111       Guice.createInjector(new AbstractModule() {
112         @Override
113         protected void configure() {
114           bind(NoCxtors.class);
115           bind(AnotherNoCxtors.class);
116           binder().requireAtInjectOnConstructors();
117         }
118       });
119       fail();
120     } catch (CreationException ce) {
121       assertEquals(2, ce.getErrorMessages().size());
122       Asserts.assertContains(ce.getMessage(),
123           "1) Explicit @Inject annotations are required on constructors, but "
124           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
125           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure",
126           "2) Explicit @Inject annotations are required on constructors, but "
127           + AnotherNoCxtors.class.getName() + " has no constructors annotated with @Inject",
128           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
129     }
130   }
131 
testNoCxtors_separateOptionsForPrivateModules()132   public void testNoCxtors_separateOptionsForPrivateModules() {
133     try {
134       Guice.createInjector(new AbstractModule() {
135         @Override
136         protected void configure() {
137           bind(AnotherNoCxtors.class);
138           install(new PrivateModule() {
139             @Override
140             protected void configure() {
141               binder().requireAtInjectOnConstructors();
142               bind(NoCxtors.class);
143             }
144           });
145         }
146       });
147       fail();
148     } catch (CreationException ce) {
149       // This is testing that the parent module doesn't fail because it isn't included
150       // in the error message.
151       assertEquals(1, ce.getErrorMessages().size());
152       Asserts.assertContains(ce.getMessage(),
153           "1) Explicit @Inject annotations are required on constructors, but "
154           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
155           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
156     }
157   }
158 
testManyConstructorsButNoneWithAtInject()159   public void testManyConstructorsButNoneWithAtInject() {
160     try {
161       Guice.createInjector(new AbstractModule() {
162         @Override
163         protected void configure() {
164           bind(ManyConstructors.class);
165           binder().requireAtInjectOnConstructors();
166         }
167       });
168       fail();
169     } catch (CreationException ce) {
170       assertEquals(1, ce.getErrorMessages().size());
171       Asserts.assertContains(ce.getMessage(),
172           "1) Explicit @Inject annotations are required on constructors, but "
173           + ManyConstructors.class.getName() + " has no constructors annotated with @Inject",
174           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
175     }
176   }
177 
testRequireAtInjectStillAllowsToConstructorBindings()178   public void testRequireAtInjectStillAllowsToConstructorBindings() {
179     Injector injector = Guice.createInjector(new AbstractModule() {
180         @Override
181         protected void configure() {
182           try {
183             bind(ManyConstructors.class)
184                 .toConstructor(ManyConstructors.class.getDeclaredConstructor());
185           } catch (Exception e) {
186             throw new RuntimeException(e);
187           }
188           binder().requireAtInjectOnConstructors();
189         }
190       });
191     injector.getInstance(ManyConstructors.class);
192   }
193 
194   private static interface Interface {}
195   private static class NoCxtors implements Interface {}
196   private static class AnotherNoCxtors {}
197   private static class ManyConstructors {
ManyConstructors()198     @SuppressWarnings("unused") ManyConstructors() {}
ManyConstructors(String a)199     @SuppressWarnings("unused") ManyConstructors(String a) {}
ManyConstructors(int a)200     @SuppressWarnings("unused") ManyConstructors(int a) {}
201   }
202 }
203