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