使用Robolectric和Dagger Hilt启动Fragment时Lateinit字段未注入
Let's break down how to resolve this kotlin.UninitializedPropertyAccessException issue you're facing. I've run into similar problems before, and it usually boils down to small gaps in how the Hilt test container is set up or how Robolectric interacts with Hilt's injection lifecycle.
Step 1: Verify Your launchFragmentInHiltContainer Implementation
The official Hilt documentation's launchFragmentInHiltContainer relies on a Hilt-annotated test activity to properly scope the Fragment's injection. If your implementation is missing this, Hilt can't inject the Fragment's fields.
First, create a simple Hilt-enabled test activity:
@AndroidEntryPoint class HiltTestActivity : AppCompatActivity()
This activity acts as the host for your Fragment and lets Hilt manage the injection context.
Then, make sure your launchFragmentInHiltContainer function uses this activity correctly:
import android.content.ComponentName import android.content.Intent import android.os.Bundle import androidx.annotation.StyleRes import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentFactory import androidx.fragment.app.FragmentScenario import androidx.test.core.app.ApplicationProvider import com.google.common.base.Preconditions inline fun <reified T : Fragment> launchFragmentInHiltContainer( fragmentArgs: Bundle? = null, @StyleRes themeResId: Int = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, crossinline action: T.() -> Unit = {} ) { val startActivityIntent = Intent.makeMainActivity( ComponentName( ApplicationProvider.getApplicationContext(), HiltTestActivity::class.java ) ).putExtra(FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY, themeResId) ActivityScenario.launch<HiltTestActivity>(startActivityIntent).onActivity { activity -> val fragment: Fragment = activity.supportFragmentManager.fragmentFactory.instantiate( Preconditions.checkNotNull(T::class.java.classLoader), T::class.java.name ).apply { arguments = fragmentArgs } activity.supportFragmentManager.beginTransaction() .add(android.R.id.content, fragment, "") .commitNow() (fragment as T).action() } }
The key here is that the Fragment is added to a Hilt-aware activity, which triggers the @AndroidEntryPoint injection pipeline.
Step 2: Confirm Your Dependency Setup
Double-check your Gradle configuration to ensure all Hilt and Robolectric dependencies are aligned and properly configured:
- Project-level build.gradle:
plugins { id 'com.google.dagger.hilt.android' version '2.44' apply false // Other plugins... } - App-level build.gradle:
plugins { id 'com.google.dagger.hilt.android' // Other plugins... } android { testOptions { unitTests { includeAndroidResources = true } } } dependencies { // Hilt core implementation 'com.google.dagger:hilt-android:2.44' kapt 'com.google.dagger:hilt-compiler:2.44' // Testing dependencies testImplementation 'org.robolectric:robolectric:4.12.1' testImplementation 'com.google.dagger:hilt-android-testing:2.44' kaptTest 'com.google.dagger:hilt-compiler:2.44' // Other test dependencies... } hilt { enableTransformForLocalTests = true }
Ensure all Hilt versions match, and Robolectric uses a version compatible with your Hilt setup.
Step 3: Validate Your Injectable Class
Make sure TestClass is properly configured for Hilt injection. Either use an @Inject constructor:
class TestClass @Inject constructor() { fun some() { /* Your implementation */ } }
Or provide it via a Hilt module if it requires external dependencies:
@Module @InstallIn(FragmentComponent::class) object TestModule { @Provides fun provideTestClass(): TestClass = TestClass() }
Without this, Hilt has no way to resolve the dependency for your Fragment.
Step 4: Adjust Fragment Lifecycle Access (If Needed)
Robolectric's Fragment lifecycle execution can differ slightly from real devices. Try moving the testClass.some() call into the launchFragmentInHiltContainer action block instead of onCreate:
@Test fun checkFragmentProperty() { launchFragmentInHiltContainer<TestFragment> { testClass.some() // Access the injected field here } }
This ensures the Fragment is fully attached and injected before you access the lateinit property.
Step 5: Clean and Rebuild
Sometimes Hilt's annotation processor cache can cause issues. Run:
./gradlew clean
Then rebuild your project and re-run the test.
内容的提问来源于stack exchange,提问作者lukjar

