首页 > 解决方案 > JUnit 本地测试 - Android 上下文“未注册仪器!”

问题描述

预期的

如 Android 文档构建本地单元测试示例MyLocalUnitTestClass中所述,在本地 JUnit测试中访问 Android上下文

观察到的

运行时错误

java.lang.IllegalStateException:未注册检测!必须在注册仪器下运行。

执行

尝试的实现也可以在 Coinverse Open App GitHub 项目的test/poc分支下找到。

目录-应用程序 > src > 测试 > java

ExampleUnitTest.kt

package app.coinverse

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import org.junit.Assert.assertEquals
import org.junit.Test

class ExampleUnitTest {

    val context = ApplicationProvider.getApplicationContext<Context>()

    @Test
    fun addition_isCorrect() {
        FirebaseHelper.initialize(context)
        assertEquals(4, 2 + 2)
    }
}

build.gradle(模块:app)

库依赖项基于设置您的测试环境文档和Android 测试 Codelab build.gradle配置。唯一实现的测试类型是本地单元测试。但是,为了以防万一,包括Android 单元仪器测试的依赖项。

以下是与测试相关的代码/库。

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 24
        targetSdkVersion 28
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }

    // Gradle automatically adds 'android.test.runner' as a dependency.
    useLibrary 'android.test.runner'
    useLibrary 'android.test.base'
    useLibrary 'android.test.mock'

    testOptions {
        unitTests.includeAndroidResources = true
    }
}

dependencies {
    // Testing

    // Local Unit
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.mockito:mockito-core:2.19.0'
    testImplementation "org.hamcrest:hamcrest-all:1.3"
    testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1"
    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.1"
    testImplementation "org.robolectric:robolectric:4.3"
    testImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    testImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
    testImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
    testImplementation 'com.google.truth:truth:0.44'

    // Android Unit
    androidTestImplementation 'junit:junit:4.12'
    androidTestImplementation 'org.mockito:mockito-core:2.19.0'
    androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito:2.12.1"
    androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.1"

    // AndroidX - JVM
    testImplementation "androidx.test:core-ktx:1.2.0"
    testImplementation "androidx.test.ext:junit-ktx:1.1.1"
    testImplementation "androidx.test:rules:1.2.0"
    implementation "androidx.fragment:fragment-testing:1.2.0-alpha02"
    implementation "androidx.test:core:1.2.0"
    implementation "androidx.fragment:fragment:1.2.0-alpha02"

    // Instrumented testing
    androidTestImplementation "androidx.test:core-ktx:1.2.0"
    androidTestImplementation "androidx.test.ext:junit-ktx:1.1.1"
    androidTestImplementation "androidx.test:rules:1.2.0"
    androidTestImplementation "androidx.room:room-testing:2.1.0"
    androidTestImplementation "androidx.arch.core:core-testing:2.0.1"
    androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0"
    androidTestImplementation "androidx.test.espresso:espresso-contrib:3.2.0"
    androidTestImplementation "androidx.test.espresso:espresso-intents:3.2.0"
    androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:3.2.0"
    androidTestImplementation "org.robolectric:annotations:4.3"
    implementation "androidx.test.espresso:espresso-idling-resource:3.2.0"

    // Resolve conflicts between main and test APK:
    androidTestImplementation "androidx.annotation:annotation:1.1.0"
    androidTestImplementation "androidx.legacy:legacy-support-v4:1.0.0"
    androidTestImplementation "androidx.recyclerview:recyclerview:1.0.0"
    androidTestImplementation "androidx.appcompat:appcompat:1.0.2"
    androidTestImplementation "com.google.android.material:material:1.0.0"

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

尝试的解决方案

ExampleUnitTest.kt

@Before
fun setup() {
    val context = getApplicationContext<Context>()
}

目录- app > src > sharedTest > java

build.gradle(模块:app)

android {
        sourceSets {
            String sharedTestDir = 'src/sharedTest/java'
            test {
                java.srcDir sharedTestDir
            }
            androidTest {
                java.srcDir sharedTestDir
            }
        }
}

附录

完整的错误信息

java.lang.IllegalStateException:未注册检测!必须在注册仪器下运行。

在 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation(InstrumentationRegistry.java:45)

在 androidx.test.core.app.ApplicationProvider.getApplicationContext(ApplicationProvider.java:41)

在 app.coinverse.ExampleUnitTest.setup(ExampleUnitTest.kt:29) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

在 java.lang.reflect.Method.invoke(Method.java:498)

在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)

在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)

在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)

在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)

在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)

在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)

在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)

在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)

在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)

在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

在 org.junit.runners.ParentRunner.run(ParentRunner.java:363)

在 org.junit.runner.JUnitCore.run(JUnitCore.java:137)

在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)

在 com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)

在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)

在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

标签: androidunit-testingjunitjunit4android-testing

解决方案


解决方案

AndroidViewModel将实现重构ViewModelJose Alcérreca的帖子Locale changes 和 AndroidViewModel 反模式中所述

此重构将消除创建应用程序上下文的需要。

除了 ViewModel 重构之外,将组件作为参数传递给 ViewModel 以分离依赖项。可以在新的 ViewModel 中使用依赖注入库来创建所需的组件(即,存储库、数据库、分析等)并将它们与 ViewModel 解耦。


推荐阅读