• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Dagger Authors.
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 dagger.hilt.android;
18 
19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
20 import static com.google.common.truth.Truth.assertThat;
21 import static org.junit.Assert.assertThrows;
22 
23 import android.os.Build;
24 import androidx.activity.ComponentActivity;
25 import androidx.test.ext.junit.runners.AndroidJUnit4;
26 import dagger.Module;
27 import dagger.Provides;
28 import dagger.hilt.EntryPoint;
29 import dagger.hilt.EntryPoints;
30 import dagger.hilt.InstallIn;
31 import dagger.hilt.android.components.ActivityComponent;
32 import dagger.hilt.android.testing.BindValue;
33 import dagger.hilt.android.testing.HiltAndroidRule;
34 import dagger.hilt.android.testing.HiltAndroidTest;
35 import dagger.hilt.android.testing.HiltTestApplication;
36 import dagger.hilt.components.SingletonComponent;
37 import javax.inject.Inject;
38 import javax.inject.Named;
39 import org.junit.Rule;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.robolectric.Robolectric;
43 import org.robolectric.android.controller.ActivityController;
44 import org.robolectric.annotation.Config;
45 
46 @HiltAndroidTest
47 @RunWith(AndroidJUnit4.class)
48 // Robolectric requires Java9 to run API 29 and above, so use API 28 instead
49 @Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
50 public final class MultiTestRoot2Test {
51   private static final int INT_VALUE = 13;
52   private static final String STR_VALUE = "MultiTestRoot2TestValue";
53   private static final long LONG_VALUE = 17L;
54   private static final String BIND_VALUE_STRING = "BIND_VALUE_STRING";
55   private static final String TEST_QUALIFIER = "TEST_QUALIFIER";
56 
57   @EntryPoint
58   @InstallIn(SingletonComponent.class)
59   public interface BindValueEntryPoint {
60     @Named(TEST_QUALIFIER)
bindValueString()61     String bindValueString();
62   }
63 
64   @AndroidEntryPoint(ComponentActivity.class)
65   public static class TestActivity extends Hilt_MultiTestRoot2Test_TestActivity {
66     @Inject Baz baz;
67     @Inject @MultiTestRootExternalModules.External Long externalLongValue;
68   }
69 
70   @Module
71   @InstallIn(ActivityComponent.class)
72   public interface TestActivityModule {
73     @Provides
provideBaz()74     static Baz provideBaz() {
75       return new Baz(LONG_VALUE);
76     }
77   }
78 
79   @Module
80   @InstallIn(SingletonComponent.class)
81   interface PkgPrivateTestModule {
82     @Provides
provideQux()83     static Qux provideQux() {
84       return new Qux();
85     }
86   }
87 
88   @Module
89   @InstallIn(SingletonComponent.class)
90   public interface TestModule {
91     @Provides
provideInt()92     static int provideInt() {
93       return INT_VALUE;
94     }
95 
96     @Provides
provideString()97     static String provideString() {
98       return STR_VALUE;
99     }
100   }
101 
102   public static final class Outer {
103     @Module
104     @InstallIn(SingletonComponent.class)
105     public interface NestedTestModule {
106       @Provides
provideLong()107       static long provideLong() {
108         return LONG_VALUE;
109       }
110     }
111 
Outer()112     private Outer() {}
113   }
114 
115   static class Foo {
116     final int value;
117 
118     @Inject
Foo(int value)119     Foo(int value) {
120       this.value = value;
121     }
122   }
123 
124   // Must be public due to b/183636779
125   public static class Bar {
126     final String value;
127 
Bar(String value)128     Bar(String value) {
129       this.value = value;
130     }
131   }
132 
133   static class Baz {
134     final long value;
135 
Baz(long value)136     Baz(long value) {
137       this.value = value;
138     }
139   }
140 
141   // Must be public due to b/183636779
142   public static class Qux {}
143 
144   @Module
145   @InstallIn(SingletonComponent.class)
146   public interface BarModule {
147     @Provides
provideBar(String value)148     static Bar provideBar(String value) {
149       return new Bar(value);
150     }
151   }
152 
153   @EntryPoint
154   @InstallIn(SingletonComponent.class)
155   public interface BarEntryPoint {
getBar()156     Bar getBar();
157   }
158 
159   @EntryPoint
160   @InstallIn(SingletonComponent.class)
161   interface PkgPrivateQuxEntryPoint {
getQux()162     Qux getQux();
163   }
164 
165   @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
166 
167   @Inject Foo foo;
168   @Inject Qux qux;
169   @Inject String str;
170   @Inject Long longValue;
171   @Inject @MultiTestRootExternalModules.External String externalStrValue;
172 
173   @BindValue
174   @Named(TEST_QUALIFIER)
175   String bindValueString = BIND_VALUE_STRING;
176 
177   @Test
testInjectFromTestModule()178   public void testInjectFromTestModule() throws Exception {
179     assertThat(foo).isNull();
180     rule.inject();
181     assertThat(foo).isNotNull();
182     assertThat(foo.value).isEqualTo(INT_VALUE);
183   }
184 
185   @Test
testInjectFromTestModuleWithArgs()186   public void testInjectFromTestModuleWithArgs() throws Exception {
187     assertThat(str).isNull();
188     rule.inject();
189     assertThat(str).isNotNull();
190     assertThat(str).isEqualTo(STR_VALUE);
191   }
192 
193   @Test
testInjectFromNestedTestModule()194   public void testInjectFromNestedTestModule() throws Exception {
195     assertThat(longValue).isNull();
196     rule.inject();
197     assertThat(longValue).isNotNull();
198     assertThat(longValue).isEqualTo(LONG_VALUE);
199   }
200 
201   @Test
testInjectFromPkgPrivateTestModule()202   public void testInjectFromPkgPrivateTestModule() throws Exception {
203     assertThat(qux).isNull();
204     rule.inject();
205     assertThat(qux).isNotNull();
206   }
207 
208   @Test
testInjectFromExternalAppModule()209   public void testInjectFromExternalAppModule() throws Exception {
210     assertThat(externalStrValue).isNull();
211     rule.inject();
212     assertThat(externalStrValue).isNotNull();
213     assertThat(externalStrValue).isEqualTo(MultiTestRootExternalModules.EXTERNAL_STR_VALUE);
214   }
215 
216   @Test
testInjectFromExternalActivityModule()217   public void testInjectFromExternalActivityModule() throws Exception {
218     rule.inject();
219     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
220     assertThat(ac.get().externalLongValue).isNull();
221     ac.create();
222     assertThat(ac.get().externalLongValue).isNotNull();
223     assertThat(ac.get().externalLongValue)
224         .isEqualTo(MultiTestRootExternalModules.EXTERNAL_LONG_VALUE);
225   }
226 
227   @Test
testLocalEntryPoint()228   public void testLocalEntryPoint() throws Exception {
229     rule.inject();
230     Bar bar = EntryPoints.get(getApplicationContext(), BarEntryPoint.class).getBar();
231     assertThat(bar).isNotNull();
232     assertThat(bar.value).isEqualTo(STR_VALUE);
233   }
234 
235   @Test
testLocalPkgPrivateEntryPoint()236   public void testLocalPkgPrivateEntryPoint() throws Exception {
237     rule.inject();
238     Qux qux = EntryPoints.get(getApplicationContext(), PkgPrivateQuxEntryPoint.class).getQux();
239     assertThat(qux).isNotNull();
240   }
241 
242   @Test
testAndroidEntryPoint()243   public void testAndroidEntryPoint() throws Exception {
244     rule.inject();
245     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
246     assertThat(ac.get().baz).isNull();
247     ac.create();
248     assertThat(ac.get().baz).isNotNull();
249     assertThat(ac.get().baz.value).isEqualTo(LONG_VALUE);
250   }
251 
252   @Test
testMissingMultiTestRoot1EntryPoint()253   public void testMissingMultiTestRoot1EntryPoint() throws Exception {
254     rule.inject();
255     ClassCastException exception =
256         assertThrows(
257             ClassCastException.class,
258             () -> EntryPoints.get(getApplicationContext(), MultiTestRoot1Test.BarEntryPoint.class));
259     assertThat(exception)
260         .hasMessageThat()
261         .isEqualTo(
262             "Cannot cast dagger.hilt.android.internal.testing.root."
263                 + "DaggerMultiTestRoot2Test_HiltComponents_SingletonC"
264                 + " to dagger.hilt.android.MultiTestRoot1Test$BarEntryPoint");
265   }
266 
267   @Test
testBindValueFieldIsProvided()268   public void testBindValueFieldIsProvided() throws Exception {
269     rule.inject();
270     assertThat(bindValueString).isEqualTo(BIND_VALUE_STRING);
271     assertThat(getBinding()).isEqualTo(BIND_VALUE_STRING);
272   }
273 
274   @Test
testBindValueIsMutable()275   public void testBindValueIsMutable() throws Exception {
276     rule.inject();
277     bindValueString = "newValue";
278     assertThat(getBinding()).isEqualTo("newValue");
279   }
280 
getBinding()281   private static String getBinding() {
282     return EntryPoints.get(getApplicationContext(), BindValueEntryPoint.class).bindValueString();
283   }
284 }
285