• 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   static class Bar {
125     final String value;
126 
Bar(String value)127     Bar(String value) {
128       this.value = value;
129     }
130   }
131 
132   static class Baz {
133     final long value;
134 
Baz(long value)135     Baz(long value) {
136       this.value = value;
137     }
138   }
139 
140   static class Qux {}
141 
142   @Module
143   @InstallIn(SingletonComponent.class)
144   public interface BarModule {
145     @Provides
provideBar(String value)146     static Bar provideBar(String value) {
147       return new Bar(value);
148     }
149   }
150 
151   @EntryPoint
152   @InstallIn(SingletonComponent.class)
153   public interface BarEntryPoint {
getBar()154     Bar getBar();
155   }
156 
157   @EntryPoint
158   @InstallIn(SingletonComponent.class)
159   interface PkgPrivateQuxEntryPoint {
getQux()160     Qux getQux();
161   }
162 
163   @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
164 
165   @Inject Foo foo;
166   @Inject Qux qux;
167   @Inject String str;
168   @Inject Long longValue;
169   @Inject @MultiTestRootExternalModules.External String externalStrValue;
170 
171   @BindValue
172   @Named(TEST_QUALIFIER)
173   String bindValueString = BIND_VALUE_STRING;
174 
175   @Test
testInjectFromTestModule()176   public void testInjectFromTestModule() throws Exception {
177     assertThat(foo).isNull();
178     rule.inject();
179     assertThat(foo).isNotNull();
180     assertThat(foo.value).isEqualTo(INT_VALUE);
181   }
182 
183   @Test
testInjectFromTestModuleWithArgs()184   public void testInjectFromTestModuleWithArgs() throws Exception {
185     assertThat(str).isNull();
186     rule.inject();
187     assertThat(str).isNotNull();
188     assertThat(str).isEqualTo(STR_VALUE);
189   }
190 
191   @Test
testInjectFromNestedTestModule()192   public void testInjectFromNestedTestModule() throws Exception {
193     assertThat(longValue).isNull();
194     rule.inject();
195     assertThat(longValue).isNotNull();
196     assertThat(longValue).isEqualTo(LONG_VALUE);
197   }
198 
199   @Test
testInjectFromPkgPrivateTestModule()200   public void testInjectFromPkgPrivateTestModule() throws Exception {
201     assertThat(qux).isNull();
202     rule.inject();
203     assertThat(qux).isNotNull();
204   }
205 
206   @Test
testInjectFromExternalAppModule()207   public void testInjectFromExternalAppModule() throws Exception {
208     assertThat(externalStrValue).isNull();
209     rule.inject();
210     assertThat(externalStrValue).isNotNull();
211     assertThat(externalStrValue).isEqualTo(MultiTestRootExternalModules.EXTERNAL_STR_VALUE);
212   }
213 
214   @Test
testInjectFromExternalActivityModule()215   public void testInjectFromExternalActivityModule() throws Exception {
216     rule.inject();
217     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
218     assertThat(ac.get().externalLongValue).isNull();
219     ac.create();
220     assertThat(ac.get().externalLongValue).isNotNull();
221     assertThat(ac.get().externalLongValue)
222         .isEqualTo(MultiTestRootExternalModules.EXTERNAL_LONG_VALUE);
223   }
224 
225   @Test
testLocalEntryPoint()226   public void testLocalEntryPoint() throws Exception {
227     rule.inject();
228     Bar bar = EntryPoints.get(getApplicationContext(), BarEntryPoint.class).getBar();
229     assertThat(bar).isNotNull();
230     assertThat(bar.value).isEqualTo(STR_VALUE);
231   }
232 
233   @Test
testLocalPkgPrivateEntryPoint()234   public void testLocalPkgPrivateEntryPoint() throws Exception {
235     rule.inject();
236     Qux qux = EntryPoints.get(getApplicationContext(), PkgPrivateQuxEntryPoint.class).getQux();
237     assertThat(qux).isNotNull();
238   }
239 
240   @Test
testAndroidEntryPoint()241   public void testAndroidEntryPoint() throws Exception {
242     rule.inject();
243     ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
244     assertThat(ac.get().baz).isNull();
245     ac.create();
246     assertThat(ac.get().baz).isNotNull();
247     assertThat(ac.get().baz.value).isEqualTo(LONG_VALUE);
248   }
249 
250   @Test
testMissingMultiTestRoot1EntryPoint()251   public void testMissingMultiTestRoot1EntryPoint() throws Exception {
252     rule.inject();
253     ClassCastException exception =
254         assertThrows(
255             ClassCastException.class,
256             () -> EntryPoints.get(getApplicationContext(), MultiTestRoot1Test.BarEntryPoint.class));
257     assertThat(exception)
258           .hasMessageThat()
259           .isEqualTo(
260               "Cannot cast dagger.hilt.android.DaggerMultiTestRoot2Test_HiltComponents_SingletonC"
261               + " to dagger.hilt.android.MultiTestRoot1Test$BarEntryPoint");
262   }
263 
264   @Test
testBindValueFieldIsProvided()265   public void testBindValueFieldIsProvided() throws Exception {
266     rule.inject();
267     assertThat(bindValueString).isEqualTo(BIND_VALUE_STRING);
268     assertThat(getBinding()).isEqualTo(BIND_VALUE_STRING);
269   }
270 
271   @Test
testBindValueIsMutable()272   public void testBindValueIsMutable() throws Exception {
273     rule.inject();
274     bindValueString = "newValue";
275     assertThat(getBinding()).isEqualTo("newValue");
276   }
277 
getBinding()278   private static String getBinding() {
279     return EntryPoints.get(getApplicationContext(), BindValueEntryPoint.class).bindValueString();
280   }
281 }
282