简体   繁体   中英

Hilt Test Unit with View Model, No Instrumentation Registered

I want to implementation Dependecy Injection using Hilt to ViewModel. And that working. but i can't test it. it show error. I was read some other post, but no one is answered.

This error maybe too many test dependency and conflict.

Version

Hilt version = 2.35.1 Android Studio = 4.2.1

Test class

simplest code won't run

package com.unlink.moviecatalogue6.ui.movie

import com.unlink.moviecatalogue6.data.repository.MovieRepository
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject

@HiltAndroidTest
class MovieViewModelTest {

    @get:Rule var hiltrule = HiltAndroidRule(this)

    @Inject
    lateinit var repository: MovieRepository

    @Before
    fun setUp() {
        hiltrule.inject()
    }

    @Test
    fun some(){
        //
    }
}

Error

but error at @get:Rule

java.lang.IllegalStateException: No instrumentation registered! Must run under a registering instrumentation.

    at androidx.test.platform.app.InstrumentationRegistry.getInstrumentation(InstrumentationRegistry.java:45)
    at androidx.test.core.app.ApplicationProvider.getApplicationContext(ApplicationProvider.java:41)
    at dagger.hilt.android.internal.testing.MarkThatRulesRanRule.<init>(MarkThatRulesRanRule.java:41)
    at dagger.hilt.android.testing.HiltAndroidRule.<init>(HiltAndroidRule.java:36)
    at com.unlink.moviecatalogue6.ui.movie.MovieViewModelTest2.<init>(MovieViewModelTest2.kt:19)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260)
    at org.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

Setup Custom Test Runner

i try make custom test runner

package com.unlink.moviecatalogue6

class CustomTestRunnerByMe : AndroidJUnitRunner() {
    override fun newApplication(
        cl: ClassLoader?,
        className: String?,
        context: Context?
    ): Application {
        return super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}

here my full build.gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'

}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    buildFeatures{

        viewBinding true
    }


    defaultConfig {
        applicationId "com.unlink.moviecatalogue6"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        //custom test runner
        testInstrumentationRunner "com.unlink.moviecatalogue6.CustomTestRunnerByMe"
        //testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled false
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    // viewmodels
    implementation 'androidx.activity:activity-ktx:1.2.3'
    implementation 'androidx.fragment:fragment-ktx:1.3.3'

    //image library
    implementation 'de.hdodenhof:circleimageview:3.1.0'
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.palette:palette-ktx:1.0.0'



    //Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.2"
    implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2"

    //Kotlin Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version"

    //Hilt
    implementation "com.google.dagger:hilt-android:$hilt_version"
    implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
    kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
    kapt "androidx.hilt:hilt-compiler:1.0.0"

    // default testing
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'


    // mockito testing
    testImplementation "androidx.arch.core:core-testing:2.1.0"
    testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"

    //coroutine test
    //For runBlockingTest, CoroutineDispatcher etc.
    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"

    // hilt testing
    // For Robolectric tests.
    testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
    kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
    // For instrumented tests.
    androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
    kaptAndroidTest "com.google.dagger:hilt-android-compiler:$hilt_version"


    // Espresso dependencies
    androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
    androidTestImplementation "androidx.test.espresso:espresso-contrib:$espresso_version"
    androidTestImplementation "androidx.test.espresso:espresso-intents:$espresso_version"
    androidTestImplementation "androidx.test.espresso:espresso-accessibility:$espresso_version"
    androidTestImplementation "androidx.test.espresso:espresso-web:$espresso_version"
    androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espresso_version"
}

kapt{
    correctErrorTypes true
}

i was follow documentation at Hilt Documentation and Google Developer Document

Any response will very appreciate, Thanks for helping

Using RobolectricTestRunner,we can run the test that depends on the android framework without emulator or real device.

ViewModel is a android library.So to test the ViewModel need to add RobolectricTestRunner.

For that first add dependency

//Unit test 
    testImplementation 'org.robolectric:robolectric:4.4'

//UI test
androidTestImplementation 'org.robolectric:robolectric:4.4'

Then Add these code above your test class.

    @HiltAndroidTest
    @RunWith(RobolectricTestRunner.class)
    @Config(sdk = {Build.VERSION_CODES.VERSION_CODE}, application = HiltTestApplication.class)
    public class HiltMainViewModelTest{
          //your test code
}

Now your HiltCustomTestRunner will use RobolectricTestRunner to test android code.

 package com.unlink.moviecatalogue6.ui.movie import com.unlink.moviecatalogue6.data.repository.MovieRepository import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest import org.junit.Before import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import javax.inject.Inject @HiltAndroidTest @RunWith(AndroidJUnit4::class) class MovieViewModelTest { @get:Rule var hiltrule = HiltAndroidRule(this) @Inject lateinit var repository: MovieRepository @Before fun setUp() { hiltrule.inject() } @Test fun some(){ // } }

Add @RunWith(AndroidJUnit4::class)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM