xref: /aosp_15_r20/external/dagger2/javatests/dagger/hilt/android/MultiTestRoot1Test.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
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.android.testing.UninstallModules;
37 import dagger.hilt.components.SingletonComponent;
38 import javax.inject.Inject;
39 import javax.inject.Named;
40 import org.junit.Rule;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.robolectric.Robolectric;
44 import org.robolectric.android.controller.ActivityController;
45 import org.robolectric.annotation.Config;
46 
47 // TODO(bcorso): Support transitively ignoring the @Module.includes of ignored modules?
48 // TODO(bcorso): Support including non-test @UninstallModules using @UninstallModules.includes?
49 @UninstallModules({
50   MultiTestRootExternalModules.PkgPrivateAppModule.class,
51   MultiTestRootExternalModules.PkgPrivateActivityModule.class
52 })
53 @HiltAndroidTest
54 @RunWith(AndroidJUnit4.class)
55 // Robolectric requires Java9 to run API 29 and above, so use API 28 instead
56 @Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
57 public final class MultiTestRoot1Test {
58   private static final int INT_VALUE = 9;
59   private static final String STR_VALUE = "MultiTestRoot1TestValue";
60   private static final long LONG_VALUE = 11L;
61   private static final String REPLACE_EXTERNAL_STR_VALUE = "REPLACED_EXTERNAL_STR_VALUE";
62   private static final long REPLACE_EXTERNAL_LONG_VALUE = 17L;
63   private static final String BIND_VALUE_STRING = "BIND_VALUE_STRING";
64   private static final String TEST_QUALIFIER = "TEST_QUALIFIER";
65 
66   @AndroidEntryPoint(ComponentActivity.class)
67   public static class TestActivity extends Hilt_MultiTestRoot1Test_TestActivity {
68     @Inject Baz baz;
69     @Inject @MultiTestRootExternalModules.External Long externalLongValue;
70   }
71 
72   @EntryPoint
73   @InstallIn(SingletonComponent.class)
74   public interface BindValueEntryPoint {
75     @Named(TEST_QUALIFIER)
bindValueString()76     String bindValueString();
77   }
78 
79   @Module
80   @InstallIn(SingletonComponent.class)
81   public interface ReplaceExternalAppModule {
82     @Provides
83     @MultiTestRootExternalModules.External
provideString()84     static String provideString() {
85       return REPLACE_EXTERNAL_STR_VALUE;
86     }
87   }
88 
89   @Module
90   @InstallIn(ActivityComponent.class)
91   public interface ReplaceExternalActivityModule {
92     @Provides
93     @MultiTestRootExternalModules.External
provideString()94     static Long provideString() {
95       return REPLACE_EXTERNAL_LONG_VALUE;
96     }
97   }
98 
99   @Module
100   @InstallIn(ActivityComponent.class)
101   public interface TestActivityModule {
102     @Provides
provideBaz()103     static Baz provideBaz() {
104       return new Baz(LONG_VALUE);
105     }
106   }
107 
108   @Module
109   @InstallIn(SingletonComponent.class)
110   interface PkgPrivateTestModule {
111     @Provides
provideQux()112     static Qux provideQux() {
113       return new Qux();
114     }
115   }
116 
117   @Module
118   @InstallIn(SingletonComponent.class)
119   public interface TestModule {
120     @Provides
provideInt()121     static int provideInt() {
122       return INT_VALUE;
123     }
124 
125     @Provides
provideString()126     static String provideString() {
127       return STR_VALUE;
128     }
129   }
130 
131   public static final class Outer {
132     @Module
133     @InstallIn(SingletonComponent.class)
134     public interface NestedTestModule {
135       @Provides
provideLong()136       static long provideLong() {
137         return LONG_VALUE;
138       }
139     }
140 
Outer()141     private Outer() {}
142   }
143 
144   static class Foo {
145     final int value;
146 
147     @Inject
Foo(int value)148     Foo(int value) {
149       this.value = value;
150     }
151   }
152 
153   // Must be public due to b/183636779
154   public static class Bar {
155     final String value;
156 
Bar(String value)157     Bar(String value) {
158       this.value = value;
159     }
160   }
161 
162   static class Baz {
163     final long value;
164 
Baz(long value)165     Baz(long value) {
166       this.value = value;
167     }
168   }
169 
170   // Must be public due to b/183636779
171   public static class Qux {}
172 
173   @Module
174   @InstallIn(SingletonComponent.class)
175   public interface BarModule {
176     @Provides
provideBar(String value)177     static Bar provideBar(String value) {
178       return new Bar(value);
179     }
180   }
181 
182   @EntryPoint
183   @InstallIn(SingletonComponent.class)
184   public interface BarEntryPoint {
getBar()185     Bar getBar();
186   }
187 
188   @EntryPoint
189   @InstallIn(SingletonComponent.class)
190   interface PkgPrivateQuxEntryPoint {
getQux()191     Qux getQux();
192   }
193 
194   @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
195 
196   @Inject Foo foo;
197   @Inject Qux qux;
198   @Inject Long longValue;
199   @Inject @MultiTestRootExternalModules.External String externalStrValue;
200 
201   @BindValue
202   @Named(TEST_QUALIFIER)
203   String bindValueString = BIND_VALUE_STRING;
204 
205   @Test
testInjectFromTestModule()206   public void testInjectFromTestModule() throws Exception {
207     assertThat(foo).isNull();
208     setupComponent();
209     assertThat(foo).isNotNull();
210     assertThat(foo.value).isEqualTo(INT_VALUE);
211   }
212 
213   @Test
testInjectFromNestedTestModule()214   public void testInjectFromNestedTestModule() throws Exception {
215     assertThat(longValue).isNull();
216     setupComponent();
217     assertThat(longValue).isNotNull();
218     assertThat(longValue).isEqualTo(LONG_VALUE);
219   }
220 
221   @Test
testInjectFromExternalAppModule()222   public void testInjectFromExternalAppModule() throws Exception {
223     assertThat(externalStrValue).isNull();
224     setupComponent();
225     assertThat(externalStrValue).isNotNull();
226     assertThat(externalStrValue).isEqualTo(REPLACE_EXTERNAL_STR_VALUE);
227     assertThat(externalStrValue).isNotEqualTo(MultiTestRootExternalModules.EXTERNAL_STR_VALUE);
228   }
229 
230   @Test
testInjectFromExternalActivityModule()231   public void testInjectFromExternalActivityModule() throws Exception {
232     setupComponent();
233     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
234     assertThat(ac.get().externalLongValue).isNull();
235     ac.create();
236     assertThat(ac.get().externalLongValue).isNotNull();
237     assertThat(ac.get().externalLongValue).isEqualTo(REPLACE_EXTERNAL_LONG_VALUE);
238     assertThat(ac.get().externalLongValue)
239         .isNotEqualTo(MultiTestRootExternalModules.EXTERNAL_LONG_VALUE);
240   }
241 
242   @Test
testInjectFromPkgPrivateTestModule()243   public void testInjectFromPkgPrivateTestModule() throws Exception {
244     assertThat(qux).isNull();
245     setupComponent();
246     assertThat(qux).isNotNull();
247   }
248 
249   @Test
testLocalEntryPoint()250   public void testLocalEntryPoint() throws Exception {
251     setupComponent();
252     Bar bar = EntryPoints.get(getApplicationContext(), BarEntryPoint.class).getBar();
253     assertThat(bar).isNotNull();
254     assertThat(bar.value).isEqualTo(STR_VALUE);
255   }
256 
257   @Test
testLocalPkgPrivateEntryPoint()258   public void testLocalPkgPrivateEntryPoint() throws Exception {
259     setupComponent();
260     Qux qux = EntryPoints.get(getApplicationContext(), PkgPrivateQuxEntryPoint.class).getQux();
261     assertThat(qux).isNotNull();
262   }
263 
264   @Test
testAndroidEntryPoint()265   public void testAndroidEntryPoint() throws Exception {
266     setupComponent();
267     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
268     assertThat(ac.get().baz).isNull();
269     ac.create();
270     assertThat(ac.get().baz).isNotNull();
271     assertThat(ac.get().baz.value).isEqualTo(LONG_VALUE);
272   }
273 
274   @Test
testMissingMultiTestRoot2EntryPoint()275   public void testMissingMultiTestRoot2EntryPoint() throws Exception {
276     setupComponent();
277     ClassCastException exception =
278         assertThrows(
279             ClassCastException.class,
280             () -> EntryPoints.get(getApplicationContext(), MultiTestRoot2Test.BarEntryPoint.class));
281     assertThat(exception)
282         .hasMessageThat()
283         .isEqualTo(
284             "Cannot cast dagger.hilt.android.internal.testing.root."
285                 + "DaggerMultiTestRoot1Test_HiltComponents_SingletonC$SingletonCImpl"
286                 + " to dagger.hilt.android.MultiTestRoot2Test$BarEntryPoint");
287   }
288 
289   @Test
testBindValueFieldIsProvided()290   public void testBindValueFieldIsProvided() throws Exception {
291     setupComponent();
292     assertThat(bindValueString).isEqualTo(BIND_VALUE_STRING);
293     assertThat(getBinding()).isEqualTo(BIND_VALUE_STRING);
294   }
295 
296   @Test
testBindValueIsMutable()297   public void testBindValueIsMutable() throws Exception {
298     setupComponent();
299     bindValueString = "newValue";
300     assertThat(getBinding()).isEqualTo("newValue");
301   }
302 
setupComponent()303   void setupComponent() {
304     rule.inject();
305   }
306 
getBinding()307   private static String getBinding() {
308     return EntryPoints.get(getApplicationContext(), BindValueEntryPoint.class).bindValueString();
309   }
310 }
311