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.
Hilt version = 2.35.1 Android Studio = 4.2.1
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(){
//
}
}
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)
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.