google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.45k stars 2.02k forks source link

Injecting dependencies into JUnit Rules #2826

Open Zhelyazko opened 3 years ago

Zhelyazko commented 3 years ago

I'm migrating a big app from Dagger to Hilt, where we have a few JUnit Rules that had an @Inject annotated fields in them - used for things like deleting test data from Room Database, clearing some state from internal classes etc. Now when migrating to Hilt, there doesn't seem to be a way to inject an instance of let's say Room DB into a Rule.

I have a setup like this one:

RuleChain.outerRule(HiltAndroidRule(this))
                 .ClearDbRule()

I also updated our Rules so that they have something like this:

class ClearDbRule : TestRule {
    override fun apply(base: Statement, description: Description): Statement {
        val hiltEntryPoint = EntryPointAccessors.fromApplication(
            InstrumentationRegistry.getInstrumentation().targetContext,
            TestRuleEntryPoint::class.java
        )
        val daoSession = hiltEntryPoint.daoSession()     // used for GreenDao
        val roomDatabase = hiltEntryPoint.roomDatabase()

When I run our tests, I receive the following error:

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.java:37)

Is it possible somehow to inject dependencies into Test Rules? The general recommendation from Hilt is to move our logic away from Custom Application class into Rules, but without being able to inject dependencies, we can't do that.

Chang-Eric commented 3 years ago

Sorry I don't think we have any documentation on this class, but https://dagger.dev/api/latest/dagger/hilt/android/testing/OnComponentReadyRunner.OnComponentReadyListener.html is probably what you want. You can register that with OnComponentReadyRunnerand we'll call you back when the component is ready to use.

That should solve most test rule cases, though if you need it exactly at that time in the rule and cannot delay then you might still have a problem.

Chang-Eric commented 3 years ago

I added the documentation label since we should have docs on that class.