707 lines
23 KiB
Java
707 lines
23 KiB
Java
/*
|
|
* Copyright (C) 2020 The Dagger Authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package dagger.hilt.android;
|
|
|
|
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
import static org.junit.Assert.assertThrows;
|
|
import static org.junit.Assert.fail;
|
|
|
|
import android.annotation.TargetApi;
|
|
import android.app.Activity;
|
|
import android.app.IntentService;
|
|
import android.app.Service;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.IBinder;
|
|
import androidx.fragment.app.Fragment;
|
|
import androidx.fragment.app.FragmentActivity;
|
|
import android.util.AttributeSet;
|
|
import android.widget.LinearLayout;
|
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
import dagger.Module;
|
|
import dagger.Provides;
|
|
import dagger.hilt.InstallIn;
|
|
import dagger.hilt.android.components.ActivityComponent;
|
|
import dagger.hilt.android.components.FragmentComponent;
|
|
import dagger.hilt.android.components.ServiceComponent;
|
|
import dagger.hilt.android.testing.HiltAndroidRule;
|
|
import dagger.hilt.android.testing.HiltAndroidTest;
|
|
import dagger.hilt.android.testing.HiltTestApplication;
|
|
import dagger.hilt.components.SingletonComponent;
|
|
import java.lang.annotation.ElementType;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.Target;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
import javax.inject.Inject;
|
|
import javax.inject.Qualifier;
|
|
import javax.inject.Singleton;
|
|
import org.junit.Before;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.robolectric.Robolectric;
|
|
import org.robolectric.android.controller.ActivityController;
|
|
import org.robolectric.annotation.Config;
|
|
|
|
@HiltAndroidTest
|
|
@RunWith(AndroidJUnit4.class)
|
|
// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
|
|
@Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
|
|
public final class InjectionTest {
|
|
private static final String APP_BINDING = "APP_BINDING";
|
|
private static final String ACTIVITY_BINDING = "ACTIVIY_BINDING";
|
|
private static final String FRAGMENT_BINDING = "FRAGMENT_BINDING";
|
|
private static final String SERVICE_BINDING = "SERVICE_BINDING";
|
|
|
|
@Retention(RUNTIME)
|
|
@Qualifier
|
|
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface ApplicationLevel {}
|
|
|
|
@Retention(RUNTIME)
|
|
@Qualifier
|
|
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface ActivityLevel {}
|
|
|
|
@Retention(RUNTIME)
|
|
@Qualifier
|
|
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface FragmentLevel {}
|
|
|
|
@Retention(RUNTIME)
|
|
@Qualifier
|
|
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface ServiceLevel {}
|
|
|
|
/** Application level bindings */
|
|
@Module
|
|
@InstallIn(SingletonComponent.class)
|
|
static final class AppModule {
|
|
@Provides
|
|
@ApplicationLevel
|
|
static String providesAppBinding() {
|
|
return APP_BINDING;
|
|
}
|
|
|
|
@Provides
|
|
@Singleton
|
|
static AtomicLong provideCounter() {
|
|
return new AtomicLong();
|
|
}
|
|
|
|
@Provides
|
|
static Long provideCount(AtomicLong counter) {
|
|
return counter.incrementAndGet();
|
|
}
|
|
}
|
|
|
|
/** Activity level bindings */
|
|
@Module
|
|
@InstallIn(ActivityComponent.class)
|
|
static final class ActivityModule {
|
|
@Provides
|
|
@ActivityLevel
|
|
static String providesActivityBinding() {
|
|
return ACTIVITY_BINDING;
|
|
}
|
|
}
|
|
|
|
/** Fragment level bindings */
|
|
@Module
|
|
@InstallIn(FragmentComponent.class)
|
|
static final class FragmentModule {
|
|
@Provides
|
|
@FragmentLevel
|
|
static String providesFragmentBinding() {
|
|
return FRAGMENT_BINDING;
|
|
}
|
|
}
|
|
|
|
/** Service level bindings */
|
|
@Module
|
|
@InstallIn(ServiceComponent.class)
|
|
static final class ServiceModule {
|
|
@Provides
|
|
@ServiceLevel
|
|
static String providesServiceBinding() {
|
|
return SERVICE_BINDING;
|
|
}
|
|
}
|
|
|
|
/** Hilt Activity */
|
|
@AndroidEntryPoint(FragmentActivity.class)
|
|
public static final class TestActivity extends Hilt_InjectionTest_TestActivity {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ActivityLevel String activityBinding;
|
|
boolean onCreateCalled;
|
|
|
|
@Override
|
|
public void onCreate(Bundle onSavedInstanceState) {
|
|
assertThat(appBinding).isNull();
|
|
assertThat(activityBinding).isNull();
|
|
|
|
super.onCreate(onSavedInstanceState);
|
|
|
|
assertThat(appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
|
|
onCreateCalled = true;
|
|
}
|
|
}
|
|
|
|
/** Non-Hilt Activity */
|
|
public static final class NonHiltActivity extends FragmentActivity {}
|
|
|
|
/** Hilt Fragment */
|
|
@AndroidEntryPoint(Fragment.class)
|
|
public static final class TestFragment extends Hilt_InjectionTest_TestFragment {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ActivityLevel String activityBinding;
|
|
@Inject @FragmentLevel String fragmentBinding;
|
|
boolean onAttachContextCalled;
|
|
boolean onAttachActivityCalled;
|
|
|
|
@Override
|
|
public void onAttach(Context context) {
|
|
preInjectionAssert();
|
|
super.onAttach(context);
|
|
postInjectionAssert();
|
|
onAttachContextCalled = true;
|
|
}
|
|
|
|
@Override
|
|
public void onAttach(Activity activity) {
|
|
preInjectionAssert();
|
|
super.onAttach(activity);
|
|
postInjectionAssert();
|
|
onAttachActivityCalled = true;
|
|
}
|
|
|
|
private void preInjectionAssert() {
|
|
assertThat(appBinding).isNull();
|
|
assertThat(activityBinding).isNull();
|
|
assertThat(fragmentBinding).isNull();
|
|
}
|
|
|
|
private void postInjectionAssert() {
|
|
assertThat(appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
assertThat(fragmentBinding).isEqualTo(FRAGMENT_BINDING);
|
|
}
|
|
}
|
|
|
|
/** Non-Hilt Fragment */
|
|
public static final class NonHiltFragment extends Fragment {}
|
|
|
|
/** Hilt extends parameterized fragment. */
|
|
@AndroidEntryPoint(ParameterizedFragment.class)
|
|
public static final class TestParameterizedFragment
|
|
extends Hilt_InjectionTest_TestParameterizedFragment<Integer> {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ActivityLevel String activityBinding;
|
|
@Inject @FragmentLevel String fragmentBinding;
|
|
boolean onAttachContextCalled;
|
|
boolean onAttachActivityCalled;
|
|
|
|
@Override
|
|
public void onAttach(Context context) {
|
|
preInjectionAssert();
|
|
super.onAttach(context);
|
|
postInjectionAssert();
|
|
onAttachContextCalled = true;
|
|
}
|
|
|
|
@Override
|
|
public void onAttach(Activity activity) {
|
|
preInjectionAssert();
|
|
super.onAttach(activity);
|
|
postInjectionAssert();
|
|
onAttachActivityCalled = true;
|
|
}
|
|
|
|
private void preInjectionAssert() {
|
|
assertThat(appBinding).isNull();
|
|
assertThat(activityBinding).isNull();
|
|
assertThat(fragmentBinding).isNull();
|
|
}
|
|
|
|
private void postInjectionAssert() {
|
|
assertThat(appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
assertThat(fragmentBinding).isEqualTo(FRAGMENT_BINDING);
|
|
}
|
|
}
|
|
|
|
/** Non-Hilt parameterized fragment */
|
|
public static class ParameterizedFragment<T> extends Fragment {}
|
|
|
|
/** Hilt View */
|
|
@AndroidEntryPoint(LinearLayout.class)
|
|
public static final class TestView extends Hilt_InjectionTest_TestView {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ActivityLevel String activityBinding;
|
|
|
|
TestView(Context context) {
|
|
super(context);
|
|
}
|
|
|
|
TestView(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
TestView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
}
|
|
|
|
@TargetApi(21)
|
|
TestView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
}
|
|
}
|
|
|
|
/** Hilt View (With Fragment bindings) */
|
|
@WithFragmentBindings
|
|
@AndroidEntryPoint(LinearLayout.class)
|
|
public static final class TestViewWithFragmentBindings
|
|
extends Hilt_InjectionTest_TestViewWithFragmentBindings {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ActivityLevel String activityBinding;
|
|
@Inject @FragmentLevel String fragmentBinding;
|
|
|
|
TestViewWithFragmentBindings(Context context) {
|
|
super(context);
|
|
}
|
|
}
|
|
|
|
@AndroidEntryPoint(Service.class)
|
|
public static final class TestService extends Hilt_InjectionTest_TestService {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ServiceLevel String serviceBinding;
|
|
|
|
@Override
|
|
public IBinder onBind(Intent intent) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@AndroidEntryPoint(IntentService.class)
|
|
public static final class TestIntentService extends Hilt_InjectionTest_TestIntentService {
|
|
private static final String NAME = "TestIntentServiceName";
|
|
@Inject @ApplicationLevel String appBinding;
|
|
@Inject @ServiceLevel String serviceBinding;
|
|
|
|
TestIntentService() {
|
|
super(NAME);
|
|
}
|
|
|
|
@Override
|
|
public void onHandleIntent(Intent intent) {}
|
|
}
|
|
|
|
@AndroidEntryPoint(BroadcastReceiver.class)
|
|
public static final class TestBroadcastReceiver extends Hilt_InjectionTest_TestBroadcastReceiver {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
Intent lastIntent = null;
|
|
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
super.onReceive(context, intent);
|
|
lastIntent = intent;
|
|
}
|
|
}
|
|
|
|
@AndroidEntryPoint(BaseBroadcastReceiver.class)
|
|
public static final class TestBroadcastReceiverWithBaseImplementingOnReceive
|
|
extends Hilt_InjectionTest_TestBroadcastReceiverWithBaseImplementingOnReceive {
|
|
@Inject @ApplicationLevel String appBinding;
|
|
Intent baseLastIntent = null;
|
|
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
super.onReceive(context, intent);
|
|
baseLastIntent = intent;
|
|
}
|
|
}
|
|
|
|
abstract static class BaseBroadcastReceiver extends BroadcastReceiver {
|
|
Intent lastIntent = null;
|
|
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
lastIntent = intent;
|
|
}
|
|
}
|
|
|
|
@Rule public final HiltAndroidRule rule = new HiltAndroidRule(this);
|
|
|
|
@Inject @ApplicationLevel String appBinding;
|
|
|
|
@Before
|
|
public void setup() {
|
|
rule.inject();
|
|
}
|
|
|
|
@Test
|
|
public void testAppInjection() throws Exception {
|
|
assertThat(appBinding).isEqualTo(APP_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testActivityInjection() throws Exception {
|
|
ActivityController<TestActivity> controller = Robolectric.buildActivity(TestActivity.class);
|
|
|
|
assertThat(controller.get().onCreateCalled).isFalse();
|
|
controller.create();
|
|
assertThat(controller.get().onCreateCalled).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void testFragmentInjection() throws Exception {
|
|
TestFragment fragment = new TestFragment();
|
|
assertThat(fragment.onAttachContextCalled).isFalse();
|
|
assertThat(fragment.onAttachActivityCalled).isFalse();
|
|
setupFragment(TestActivity.class, fragment);
|
|
assertThat(fragment.onAttachContextCalled).isTrue();
|
|
assertThat(fragment.onAttachActivityCalled).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void testParameterizedFragmentInjection() throws Exception {
|
|
TestParameterizedFragment fragment = new TestParameterizedFragment();
|
|
assertThat(fragment.onAttachContextCalled).isFalse();
|
|
assertThat(fragment.onAttachActivityCalled).isFalse();
|
|
setupFragment(TestActivity.class, fragment);
|
|
assertThat(fragment.onAttachContextCalled).isTrue();
|
|
assertThat(fragment.onAttachActivityCalled).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void testViewNoFragmentBindingsWithActivity() throws Exception {
|
|
TestActivity activity = Robolectric.setupActivity(TestActivity.class);
|
|
TestView view = new TestView(activity);
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testViewNoFragmentBindingsWithFragment() throws Exception {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
TestView view = new TestView(fragment.getContext());
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testViewNoFragmentBindingsWithFragment_secondConstructor() throws Exception {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
TestView view = new TestView(fragment.getContext(), /* attrs= */ null);
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testViewNoFragmentBindingsWithFragment_thirdConstructor() throws Exception {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
TestView view = new TestView(fragment.getContext(), /* attrs= */ null, /* defStyleAttr= */ 0);
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
}
|
|
|
|
@Test
|
|
@Config(sdk = 21)
|
|
public void testViewNoFragmentBindingsWithFragment_fourthConstructor_presentOnTwentyOne()
|
|
throws Exception {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
TestView view =
|
|
new TestView(
|
|
fragment.getContext(), /* attrs= */ null, /* defStyleAttr= */ 0, /* defStyleRes= */ 0);
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
}
|
|
|
|
@Test
|
|
@Config(sdk = 19)
|
|
public void testViewNoFragmentBindingsWithFragment_fourthConstructor_notPresentOnTwenty() {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
|
|
assertThrows(
|
|
NoSuchMethodError.class,
|
|
() ->
|
|
new TestView(
|
|
fragment.getContext(),
|
|
/* attrs= */ null,
|
|
/* defStyleAttr= */ 0,
|
|
/* defStyleRes= */ 0));
|
|
}
|
|
|
|
@Test
|
|
public void testServiceInjection() throws Exception {
|
|
TestService testService = Robolectric.setupService(TestService.class);
|
|
assertThat(testService.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(testService.serviceBinding).isEqualTo(SERVICE_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testIntentServiceInjection() throws Exception {
|
|
TestIntentService testIntentService = Robolectric.setupService(TestIntentService.class);
|
|
assertThat(testIntentService.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(testIntentService.serviceBinding).isEqualTo(SERVICE_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testBroadcastReceiverInjection() throws Exception {
|
|
TestBroadcastReceiver testBroadcastReceiver = new TestBroadcastReceiver();
|
|
Intent intent = new Intent();
|
|
testBroadcastReceiver.onReceive(getApplicationContext(), intent);
|
|
assertThat(testBroadcastReceiver.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(testBroadcastReceiver.lastIntent).isSameInstanceAs(intent);
|
|
}
|
|
|
|
@Test
|
|
public void testBroadcastReceiverWithBaseImplementingOnReceiveInjection() throws Exception {
|
|
TestBroadcastReceiverWithBaseImplementingOnReceive testBroadcastReceiver =
|
|
new TestBroadcastReceiverWithBaseImplementingOnReceive();
|
|
Intent intent = new Intent();
|
|
testBroadcastReceiver.onReceive(getApplicationContext(), intent);
|
|
assertThat(testBroadcastReceiver.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(testBroadcastReceiver.lastIntent).isSameInstanceAs(intent);
|
|
assertThat(testBroadcastReceiver.baseLastIntent).isSameInstanceAs(intent);
|
|
}
|
|
|
|
@Test
|
|
public void testViewWithFragmentBindingsWithFragment() throws Exception {
|
|
TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
|
|
|
|
Context fragmentContext = fragment.getContext();
|
|
TestViewWithFragmentBindings view = new TestViewWithFragmentBindings(fragmentContext);
|
|
assertThat(view.appBinding).isEqualTo(APP_BINDING);
|
|
assertThat(view.activityBinding).isEqualTo(ACTIVITY_BINDING);
|
|
assertThat(view.fragmentBinding).isEqualTo(FRAGMENT_BINDING);
|
|
}
|
|
|
|
@Test
|
|
public void testViewWithFragmentBindingsFailsWithActivity() throws Exception {
|
|
TestActivity activity = Robolectric.setupActivity(TestActivity.class);
|
|
try {
|
|
new TestViewWithFragmentBindings(activity);
|
|
fail("Expected test to fail but it passes!");
|
|
} catch (IllegalStateException e) {
|
|
assertThat(e)
|
|
.hasMessageThat()
|
|
.contains(
|
|
"@WithFragmentBindings Hilt view must be attached to an @AndroidEntryPoint Fragment");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testFragmentAttachedToNonHiltActivityFails() throws Exception {
|
|
NonHiltActivity activity = Robolectric.setupActivity(NonHiltActivity.class);
|
|
try {
|
|
activity
|
|
.getSupportFragmentManager()
|
|
.beginTransaction()
|
|
.add(new TestFragment(), null)
|
|
.commitNow();
|
|
fail("Expected test to fail but it passes!");
|
|
} catch (IllegalStateException e) {
|
|
assertThat(e)
|
|
.hasMessageThat()
|
|
.contains("Hilt Fragments must be attached to an @AndroidEntryPoint Activity");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testViewAttachedToNonHiltActivityFails() throws Exception {
|
|
NonHiltActivity activity = Robolectric.setupActivity(NonHiltActivity.class);
|
|
try {
|
|
new TestView(activity);
|
|
fail("Expected test to fail but it passes!");
|
|
} catch (IllegalStateException e) {
|
|
assertThat(e)
|
|
.hasMessageThat()
|
|
.contains("Hilt view must be attached to an @AndroidEntryPoint Fragment or Activity");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testViewAttachedToNonHiltFragmentFails() throws Exception {
|
|
NonHiltActivity activity = Robolectric.setupActivity(NonHiltActivity.class);
|
|
NonHiltFragment fragment = new NonHiltFragment();
|
|
activity.getSupportFragmentManager().beginTransaction().add(fragment, null).commitNow();
|
|
Context nonHiltContext = fragment.getContext();
|
|
try {
|
|
new TestView(nonHiltContext);
|
|
fail("Expected test to fail but it passes!");
|
|
} catch (IllegalStateException e) {
|
|
assertThat(e)
|
|
.hasMessageThat()
|
|
.contains("Hilt view must be attached to an @AndroidEntryPoint Fragment or Activity");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testViewAttachedToApplicationContextFails() throws Exception {
|
|
try {
|
|
new TestView(getApplicationContext());
|
|
fail("Expected test to fail but it passes!");
|
|
} catch (IllegalStateException e) {
|
|
assertThat(e)
|
|
.hasMessageThat()
|
|
.contains(
|
|
"Hilt view cannot be created using the application context. "
|
|
+ "Use a Hilt Fragment or Activity context");
|
|
}
|
|
}
|
|
|
|
/** Hilt Activity that manually calls inject(). */
|
|
@AndroidEntryPoint(FragmentActivity.class)
|
|
public static final class DoubleInjectActivity extends Hilt_InjectionTest_DoubleInjectActivity {
|
|
@Inject Long counter;
|
|
|
|
@Override
|
|
public void onCreate(Bundle onSavedInstanceState) {
|
|
inject();
|
|
super.onCreate(onSavedInstanceState);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testActivityDoesNotInjectTwice() throws Exception {
|
|
ActivityController<DoubleInjectActivity> controller =
|
|
Robolectric.buildActivity(DoubleInjectActivity.class);
|
|
controller.create();
|
|
assertThat(controller.get().counter).isEqualTo(1L);
|
|
}
|
|
|
|
/** Hilt Fragment that manually calls inject(). */
|
|
@AndroidEntryPoint(Fragment.class)
|
|
public static final class DoubleInjectFragment extends Hilt_InjectionTest_DoubleInjectFragment {
|
|
@Inject Long counter;
|
|
|
|
@Override
|
|
public void onAttach(Context context) {
|
|
inject();
|
|
super.onAttach(context);
|
|
}
|
|
|
|
@Override
|
|
public void onAttach(Activity activity) {
|
|
inject();
|
|
super.onAttach(activity);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testFragmentDoesNotInjectTwice() throws Exception {
|
|
DoubleInjectFragment fragment = setupFragment(TestActivity.class, new DoubleInjectFragment());
|
|
assertThat(fragment.counter).isEqualTo(1L);
|
|
}
|
|
|
|
/** Hilt View that manually calls inject(). */
|
|
@AndroidEntryPoint(LinearLayout.class)
|
|
public static final class DoubleInjectView extends Hilt_InjectionTest_DoubleInjectView {
|
|
@Inject Long counter;
|
|
|
|
DoubleInjectView(Context context) {
|
|
super(context);
|
|
inject();
|
|
}
|
|
|
|
DoubleInjectView(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
inject();
|
|
}
|
|
|
|
DoubleInjectView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
inject();
|
|
}
|
|
|
|
@TargetApi(21)
|
|
DoubleInjectView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
inject();
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testViewDoesNotInjectTwice() throws Exception {
|
|
TestActivity activity = Robolectric.setupActivity(TestActivity.class);
|
|
DoubleInjectView view = new DoubleInjectView(activity);
|
|
assertThat(view.counter).isEqualTo(1L);
|
|
}
|
|
|
|
/** Hilt Service that manually calls inject(). */
|
|
@AndroidEntryPoint(Service.class)
|
|
public static final class DoubleInjectService extends Hilt_InjectionTest_DoubleInjectService {
|
|
@Inject Long counter;
|
|
|
|
@Override public void onCreate() {
|
|
inject();
|
|
super.onCreate();
|
|
}
|
|
|
|
@Override
|
|
public IBinder onBind(Intent intent) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testServiceDoesNotInjectTwice() throws Exception {
|
|
DoubleInjectService testService = Robolectric.setupService(DoubleInjectService.class);
|
|
assertThat(testService.counter).isEqualTo(1L);
|
|
}
|
|
|
|
/** Hilt BroadcastReceiver that manually calls inject(). */
|
|
@AndroidEntryPoint(BroadcastReceiver.class)
|
|
public static final class DoubleInjectBroadcastReceiver
|
|
extends Hilt_InjectionTest_DoubleInjectBroadcastReceiver {
|
|
@Inject Long counter;
|
|
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
inject(context);
|
|
super.onReceive(context, intent);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testBroadcastReceiverDoesNotInjectTwice() throws Exception {
|
|
DoubleInjectBroadcastReceiver testBroadcastReceiver = new DoubleInjectBroadcastReceiver();
|
|
Intent intent = new Intent();
|
|
testBroadcastReceiver.onReceive(getApplicationContext(), intent);
|
|
assertThat(testBroadcastReceiver.counter).isEqualTo(1L);
|
|
}
|
|
|
|
private static <T extends Fragment> T setupFragment(
|
|
Class<? extends FragmentActivity> activityClass, T fragment) {
|
|
FragmentActivity activity = Robolectric.setupActivity(activityClass);
|
|
attachFragment(activity, fragment);
|
|
return fragment;
|
|
}
|
|
|
|
private static void attachFragment(FragmentActivity activity, Fragment fragment) {
|
|
activity.getSupportFragmentManager().beginTransaction().add(fragment, "").commitNow();
|
|
}
|
|
}
|