繁体   English   中英

JUnit 本地测试 - Android 上下文“未注册检测!”

[英]JUnit Local Test - Android Context 'No instrumentation registered!'

预期的

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

观察到的

运行时错误

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

执行

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

目录- app > src > test > java

示例UnitTest.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 UnitInstrumented测试的依赖项。

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

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"
}

尝试的解决方案

  • 文件 > 使缓存无效并重新启动...
  • 在运行导致相同运行时错误的测试之前启动上下文。

示例UnitTest.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)

解决方案

AndroidViewModel实现重构为ViewModel ,如Jose Alcérreca的 post Locale changes 和 AndroidViewModel antipattern 中所述

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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