dagger: Exception when running instrumented tests with Hilt and App Startup

Hello,

I am starting to setup some instrumented tests on my project, but when I run them, I get the following exception on logcat:

2022-04-11 10:41:09.352 24409-24409/com.example.appstartupinstrumentationtest E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.appstartupinstrumentationtest, PID: 24409
    java.lang.RuntimeException: Unable to get provider androidx.startup.InitializationProvider: androidx.startup.StartupException: java.lang.IllegalStateException: The component was not created. Check that you have added the HiltAndroidRule.
        at android.app.ActivityThread.installProvider(ActivityThread.java:8195)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:7726)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7546)
        at android.app.ActivityThread.access$1500(ActivityThread.java:301)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2166)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8633)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
     Caused by: androidx.startup.StartupException: java.lang.IllegalStateException: The component was not created. Check that you have added the HiltAndroidRule.
        at androidx.startup.AppInitializer.doInitialize(AppInitializer.java:162)
        at androidx.startup.AppInitializer.discoverAndInitialize(AppInitializer.java:198)
        at androidx.startup.InitializationProvider.onCreate(InitializationProvider.java:38)
        at android.content.ContentProvider.attachInfo(ContentProvider.java:2429)
        at android.content.ContentProvider.attachInfo(ContentProvider.java:2399)
        at android.app.ActivityThread.installProvider(ActivityThread.java:8190)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:7726) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7546) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:301) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2166) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:246) 
        at android.app.ActivityThread.main(ActivityThread.java:8633) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 
     Caused by: java.lang.IllegalStateException: The component was not created. Check that you have added the HiltAndroidRule.
        at dagger.hilt.internal.Preconditions.checkState(Preconditions.java:83)
        at dagger.hilt.android.internal.testing.TestApplicationComponentManager.generatedComponent(TestApplicationComponentManager.java:96)
        at dagger.hilt.android.testing.HiltTestApplication.generatedComponent(HiltTestApplication.java:49)
        at dagger.hilt.EntryPoints.get(EntryPoints.java:59)
        at dagger.hilt.android.EntryPointAccessors.fromApplication(EntryPointAccessors.kt:35)
        at com.example.appstartupinstrumentationtest.InitializerEntryPoint$Companion.resolve(InitializerEntryPoint.kt:20)
        at com.example.appstartupinstrumentationtest.SomeComponentInitializer.create(SomeComponentInitializer.kt:10)
        at com.example.appstartupinstrumentationtest.SomeComponentInitializer.create(SomeComponentInitializer.kt:7)
        at androidx.startup.AppInitializer.doInitialize(AppInitializer.java:155)
        at androidx.startup.AppInitializer.discoverAndInitialize(AppInitializer.java:198) 
        at androidx.startup.InitializationProvider.onCreate(InitializationProvider.java:38) 
        at android.content.ContentProvider.attachInfo(ContentProvider.java:2429) 
        at android.content.ContentProvider.attachInfo(ContentProvider.java:2399) 
        at android.app.ActivityThread.installProvider(ActivityThread.java:8190) 
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:7726) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7546) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:301) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2166) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:246) 
        at android.app.ActivityThread.main(ActivityThread.java:8633) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

My real codebase is much more complex, but I created a much simpler project where I am able to reproduce the issue HERE.

From what I understood, when running the instrumentation tests, the startup code is first executed, even before anything on the test class (Before and BeforeClass annotated methods).

What is the best way to handle this? Is this something that was already detected?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 19

Commits related to this issue

Most upvoted comments

It looks like the issue is that Androidx ApplicationProvider#getApplicationContext() is not set by the time ContentProvider#attachInfo() is called, which seems like the place the androidx.startup library has decided to initialize everything.

I think we could likely fix this by passing in the application manually here:

https://github.com/google/dagger/blob/master/java/dagger/hilt/android/EarlyEntryPoints.java#L61

rather than trying to get the application instance via ApplicationProvider.

I’ll test this out and report back.

Hi @ampeixoto, you’ll want to use EarlyEntryPoint for the entry point that is referenced in your stacktrace.