1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2021 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 com.google.common.truth.Truth.assertThat; 20*f585d8a3SJacky Wang import static java.lang.annotation.RetentionPolicy.CLASS; 21*f585d8a3SJacky Wang 22*f585d8a3SJacky Wang import android.content.Context; 23*f585d8a3SJacky Wang import android.os.Build; 24*f585d8a3SJacky Wang import androidx.activity.ComponentActivity; 25*f585d8a3SJacky Wang import androidx.test.core.app.ActivityScenario; 26*f585d8a3SJacky Wang import androidx.test.ext.junit.runners.AndroidJUnit4; 27*f585d8a3SJacky Wang import dagger.Module; 28*f585d8a3SJacky Wang import dagger.Provides; 29*f585d8a3SJacky Wang import dagger.hilt.DefineComponent; 30*f585d8a3SJacky Wang import dagger.hilt.EntryPoint; 31*f585d8a3SJacky Wang import dagger.hilt.EntryPoints; 32*f585d8a3SJacky Wang import dagger.hilt.InstallIn; 33*f585d8a3SJacky Wang import dagger.hilt.android.components.ActivityComponent; 34*f585d8a3SJacky Wang import dagger.hilt.android.qualifiers.ApplicationContext; 35*f585d8a3SJacky Wang import dagger.hilt.android.scopes.ActivityScoped; 36*f585d8a3SJacky Wang import dagger.hilt.android.testing.HiltAndroidRule; 37*f585d8a3SJacky Wang import dagger.hilt.android.testing.HiltAndroidTest; 38*f585d8a3SJacky Wang import dagger.hilt.android.testing.HiltTestApplication; 39*f585d8a3SJacky Wang import dagger.hilt.components.SingletonComponent; 40*f585d8a3SJacky Wang import dagger.hilt.migration.AliasOf; 41*f585d8a3SJacky Wang import java.lang.annotation.ElementType; 42*f585d8a3SJacky Wang import java.lang.annotation.Retention; 43*f585d8a3SJacky Wang import java.lang.annotation.Target; 44*f585d8a3SJacky Wang import javax.inject.Inject; 45*f585d8a3SJacky Wang import javax.inject.Provider; 46*f585d8a3SJacky Wang import javax.inject.Scope; 47*f585d8a3SJacky Wang import org.junit.Before; 48*f585d8a3SJacky Wang import org.junit.Rule; 49*f585d8a3SJacky Wang import org.junit.Test; 50*f585d8a3SJacky Wang import org.junit.runner.RunWith; 51*f585d8a3SJacky Wang import org.robolectric.annotation.Config; 52*f585d8a3SJacky Wang 53*f585d8a3SJacky Wang @HiltAndroidTest 54*f585d8a3SJacky Wang @RunWith(AndroidJUnit4.class) 55*f585d8a3SJacky Wang @Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class) 56*f585d8a3SJacky Wang public final class AliasOfMultipleScopesTest { 57*f585d8a3SJacky Wang 58*f585d8a3SJacky Wang @Rule public final HiltAndroidRule rule = new HiltAndroidRule(this); 59*f585d8a3SJacky Wang 60*f585d8a3SJacky Wang @Inject @ApplicationContext Context context; 61*f585d8a3SJacky Wang @Inject CustomComponent.Builder customComponentBuilder; 62*f585d8a3SJacky Wang 63*f585d8a3SJacky Wang @Scope 64*f585d8a3SJacky Wang @Retention(CLASS) 65*f585d8a3SJacky Wang @Target({ElementType.METHOD, ElementType.TYPE}) 66*f585d8a3SJacky Wang public @interface CustomScoped {} 67*f585d8a3SJacky Wang 68*f585d8a3SJacky Wang @DefineComponent(parent = SingletonComponent.class) 69*f585d8a3SJacky Wang @CustomScoped 70*f585d8a3SJacky Wang public interface CustomComponent { 71*f585d8a3SJacky Wang @DefineComponent.Builder 72*f585d8a3SJacky Wang public interface Builder { build()73*f585d8a3SJacky Wang CustomComponent build(); 74*f585d8a3SJacky Wang } 75*f585d8a3SJacky Wang } 76*f585d8a3SJacky Wang 77*f585d8a3SJacky Wang @Scope 78*f585d8a3SJacky Wang @AliasOf({ActivityScoped.class, CustomScoped.class}) 79*f585d8a3SJacky Wang public @interface AliasScoped {} 80*f585d8a3SJacky Wang 81*f585d8a3SJacky Wang public interface UnscopedDep {} 82*f585d8a3SJacky Wang 83*f585d8a3SJacky Wang public interface ActivityScopedDep {} 84*f585d8a3SJacky Wang 85*f585d8a3SJacky Wang public interface CustomScopedDep {} 86*f585d8a3SJacky Wang 87*f585d8a3SJacky Wang public interface AliasScopedDep {} 88*f585d8a3SJacky Wang 89*f585d8a3SJacky Wang @Module 90*f585d8a3SJacky Wang @InstallIn(SingletonComponent.class) 91*f585d8a3SJacky Wang interface SingletonTestModule { 92*f585d8a3SJacky Wang @Provides unscopedDep()93*f585d8a3SJacky Wang static UnscopedDep unscopedDep() { 94*f585d8a3SJacky Wang return new UnscopedDep() {}; 95*f585d8a3SJacky Wang } 96*f585d8a3SJacky Wang } 97*f585d8a3SJacky Wang 98*f585d8a3SJacky Wang @Module 99*f585d8a3SJacky Wang @InstallIn(ActivityComponent.class) 100*f585d8a3SJacky Wang interface ActivityTestModule { 101*f585d8a3SJacky Wang @Provides 102*f585d8a3SJacky Wang @ActivityScoped activityScopedDep()103*f585d8a3SJacky Wang static ActivityScopedDep activityScopedDep() { 104*f585d8a3SJacky Wang return new ActivityScopedDep() {}; 105*f585d8a3SJacky Wang } 106*f585d8a3SJacky Wang 107*f585d8a3SJacky Wang @Provides 108*f585d8a3SJacky Wang @AliasScoped aliasScopedDep()109*f585d8a3SJacky Wang static AliasScopedDep aliasScopedDep() { 110*f585d8a3SJacky Wang return new AliasScopedDep() {}; 111*f585d8a3SJacky Wang } 112*f585d8a3SJacky Wang } 113*f585d8a3SJacky Wang 114*f585d8a3SJacky Wang @Module 115*f585d8a3SJacky Wang @InstallIn(CustomComponent.class) 116*f585d8a3SJacky Wang interface CustomTestModule { 117*f585d8a3SJacky Wang @Provides 118*f585d8a3SJacky Wang @CustomScoped customScopedDep()119*f585d8a3SJacky Wang static CustomScopedDep customScopedDep() { 120*f585d8a3SJacky Wang return new CustomScopedDep() {}; 121*f585d8a3SJacky Wang } 122*f585d8a3SJacky Wang 123*f585d8a3SJacky Wang @Provides 124*f585d8a3SJacky Wang @AliasScoped aliasScopedDep()125*f585d8a3SJacky Wang static AliasScopedDep aliasScopedDep() { 126*f585d8a3SJacky Wang return new AliasScopedDep() {}; 127*f585d8a3SJacky Wang } 128*f585d8a3SJacky Wang } 129*f585d8a3SJacky Wang 130*f585d8a3SJacky Wang /** An activity to test injection. */ 131*f585d8a3SJacky Wang @AndroidEntryPoint(ComponentActivity.class) 132*f585d8a3SJacky Wang public static final class TestActivity extends Hilt_AliasOfMultipleScopesTest_TestActivity { 133*f585d8a3SJacky Wang @Inject Provider<UnscopedDep> unscopedDep; 134*f585d8a3SJacky Wang @Inject Provider<ActivityScopedDep> activityScopedDep; 135*f585d8a3SJacky Wang @Inject Provider<AliasScopedDep> aliasScopedDep; 136*f585d8a3SJacky Wang } 137*f585d8a3SJacky Wang 138*f585d8a3SJacky Wang @EntryPoint 139*f585d8a3SJacky Wang @InstallIn(SingletonComponent.class) 140*f585d8a3SJacky Wang interface CustomComponentBuilderEntryPoint { customComponentBuilder()141*f585d8a3SJacky Wang CustomComponent.Builder customComponentBuilder(); 142*f585d8a3SJacky Wang } 143*f585d8a3SJacky Wang 144*f585d8a3SJacky Wang @EntryPoint 145*f585d8a3SJacky Wang @InstallIn(CustomComponent.class) 146*f585d8a3SJacky Wang interface CustomComponentEntryPoint { unscopedDep()147*f585d8a3SJacky Wang Provider<UnscopedDep> unscopedDep(); 148*f585d8a3SJacky Wang customScopedDep()149*f585d8a3SJacky Wang Provider<CustomScopedDep> customScopedDep(); 150*f585d8a3SJacky Wang aliasScopedDep()151*f585d8a3SJacky Wang Provider<AliasScopedDep> aliasScopedDep(); 152*f585d8a3SJacky Wang } 153*f585d8a3SJacky Wang 154*f585d8a3SJacky Wang @Before setUp()155*f585d8a3SJacky Wang public void setUp() { 156*f585d8a3SJacky Wang rule.inject(); 157*f585d8a3SJacky Wang } 158*f585d8a3SJacky Wang 159*f585d8a3SJacky Wang @Test testActivityScoped()160*f585d8a3SJacky Wang public void testActivityScoped() { 161*f585d8a3SJacky Wang try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) { 162*f585d8a3SJacky Wang scenario.onActivity( 163*f585d8a3SJacky Wang activity -> { 164*f585d8a3SJacky Wang assertThat(activity.unscopedDep.get()).isNotSameInstanceAs(activity.unscopedDep.get()); 165*f585d8a3SJacky Wang assertThat(activity.activityScopedDep.get()) 166*f585d8a3SJacky Wang .isSameInstanceAs(activity.activityScopedDep.get()); 167*f585d8a3SJacky Wang assertThat(activity.aliasScopedDep.get()) 168*f585d8a3SJacky Wang .isSameInstanceAs(activity.aliasScopedDep.get()); 169*f585d8a3SJacky Wang }); 170*f585d8a3SJacky Wang } 171*f585d8a3SJacky Wang } 172*f585d8a3SJacky Wang 173*f585d8a3SJacky Wang @Test testCustomScoped()174*f585d8a3SJacky Wang public void testCustomScoped() { 175*f585d8a3SJacky Wang CustomComponent customComponent = 176*f585d8a3SJacky Wang EntryPoints.get(context, CustomComponentBuilderEntryPoint.class) 177*f585d8a3SJacky Wang .customComponentBuilder() 178*f585d8a3SJacky Wang .build(); 179*f585d8a3SJacky Wang CustomComponentEntryPoint entryPoint = 180*f585d8a3SJacky Wang EntryPoints.get(customComponent, CustomComponentEntryPoint.class); 181*f585d8a3SJacky Wang assertThat(entryPoint.unscopedDep().get()).isNotSameInstanceAs(entryPoint.unscopedDep().get()); 182*f585d8a3SJacky Wang assertThat(entryPoint.customScopedDep().get()) 183*f585d8a3SJacky Wang .isSameInstanceAs(entryPoint.customScopedDep().get()); 184*f585d8a3SJacky Wang assertThat(entryPoint.aliasScopedDep().get()) 185*f585d8a3SJacky Wang .isSameInstanceAs(entryPoint.aliasScopedDep().get()); 186*f585d8a3SJacky Wang } 187*f585d8a3SJacky Wang } 188