9
votes

I'm trying to run a test using Dagger Hilt with Robolectric:

@RunWith(RobolectricTestRunner::class)
@UninstallModules(LevelModule::class, AppModule::class)
@Config(sdk = [16, 28], application = HiltTestApplication::class)
@LooperMode(LooperMode.Mode.PAUSED)
@HiltAndroidTest
class LevelFragmentTest {

    @get:Rule
    var rule = HiltAndroidRule(this)

    @Test
    fun testShowGameOverWhenTapAMine() {
        launchActivity<GameActivity>().onActivity { activity ->
            ShadowLooper.runUiThreadTasks()
            ...
        }
    }

The test fails on GameActivity.onCreate because all fields of GameActivity with @Inject are null.

GameActivity is:

@AndroidEntryPoint
class GameActivity : AppCompatActivity()

The modules are:

@Module
@InstallIn(ActivityComponent::class)
open class LevelModule { ... } 
@Module
@InstallIn(ActivityComponent::class)
class TestLevelModule {
@Module
@InstallIn(ApplicationComponent::class)
class AppModule() { ... } 
@Module
@InstallIn(ApplicationComponent::class)
class TestAppModule() { ... } 

It works when I run the app, but when I run the test, GameActivity is not being injected. All field with @Inject are null.

Does anyone have any idea of what it's wrong?


If useful, the whole code and test are here:

  • https://github.com/lucasnlm/antimine-android/pull/95

  • https://github.com/lucasnlm/antimine-android/pull/95/commits/fcc1b3782b8d456898529dd3ba2410ac5f2da6d5

EDIT

I have no ideia why, but the tests passed on this PR:

1
I cloned your repo, and the test runs, but fails, by changing Hilt's annotation processor from kapt to annotationProcessor - Saurabh Thorat
Using kapt the tests run too. But fails because they are not injected. - Lucas Lima
I have no ideia why, but the tests passed on CI. - Lucas Lima
This is a known bug when running Hilt Tests in Android Studio. They have a work around to setup a Gradle Test configuration, and run the tests through gradle instead of the IDE. Issue being tracked here: github.com/google/dagger/issues/1956 - kingargyle

1 Answers

1
votes

according to the testing guide,

you must replace the binding. Create a new module within the test class that defines the test binding:

@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {

  @Module
  @InstallIn(ApplicationComponent::class)
  abstract class TestModule {

    @Singleton
    @Binds
    abstract fun bindAnalyticsService(
      analyticsServiceImpl: AnalyticsServiceImpl
    ): AnalyticsService
  }

  ...
}