AndroidX:没有注册仪器!必须在注册仪器下运行

jul*_*iro 23 android unit-testing android-espresso android-instrumentation

我正在尝试运行一个取决于上下文的本地单元测试,并遵循本指南:https://developer.android.com/training/testing/unit-testing/local-unit-tests#kotlin 我设置像我这样的项目(点击此链接:https://developer.android.com/training/testing/set-up-project):

的build.gradle(APP)

android {
compileSdkVersion 28
buildToolsVersion '27.0.3'
defaultConfig {
    minSdkVersion 21
    targetSdkVersion 27
    versionCode 76
    versionName "2.6.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    multiDexEnabled true

useLibrary 'android.test.runner'
    useLibrary 'android.test.base'
    useLibrary 'android.test.mock'

}
testOptions {
    unitTests.returnDefaultValues = true
    unitTests.all {
        // All the usual Gradle options.
        testLogging {
            events "passed", "skipped", "failed", "standardOut", "standardError"
            outputs.upToDateWhen { false }
            showStandardStreams = true
        }
    }
    unitTests.includeAndroidResources = true

}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')

androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion", {
    exclude group: 'com.android.support', module: 'support-annotations'
})
// Espresso UI Testing dependencies
implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"

testImplementation 'androidx.test:core:1.0.0'

// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
// Espresso Assertions
androidTestImplementation 'androidx.test.ext:junit:1.0.0'
androidTestImplementation 'androidx.test.ext:truth:1.0.0'
androidTestImplementation 'com.google.truth:truth:0.42'
    implementation 'androidx.multidex:multidex:2.0.0'
}
Run Code Online (Sandbox Code Playgroud)

我的espresso_version是espressoVersion ='3.1.0'

我在module-name/src/test/java /中的测试如下所示:

    import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.instacart.library.truetime.TrueTime
import edu.mira.aula.shared.extensions.android.trueDateNow
import edu.mira.aula.shared.network.ConnectivityHelper
import kotlinx.coroutines.experimental.runBlocking
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import java.util.*
import java.util.concurrent.CountDownLatch

class TimeExtensionsUnitTest {
private lateinit var instrumentationCtx: Context

@Before
fun setup() {
    instrumentationCtx = ApplicationProvider.getApplicationContext<Context>()
}
 @Test
fun testTrueTimeValueReturnsIfInitialized() {
    if (ConnectivityHelper.isOnline(instrumentationCtx)) {
        runBlocking {
            val countDownLatch = CountDownLatch(1)
            TrueTime.build()
                    .withSharedPreferencesCache(instrumentationCtx)
                    .withConnectionTimeout(10000)
                    .initialize()
            countDownLatch.countDown()

            try {
                countDownLatch.await()
                val dateFromTrueTime = trueDateNow()
                val normalDate = Date()
                Assert.assertNotEquals(dateFromTrueTime, normalDate)
            } catch (e: InterruptedException) {
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每次我运行它,它给了我:

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)
Run Code Online (Sandbox Code Playgroud)

如果我将它作为一个仪器测试(更改包)运行它运行没有错误.但我认为本指南正是能够使用Android框架类(如Context)运行单元测试.我甚至尝试过运行class UnitTestSample但发生同样的错误.

我还从我的项目中删除了所有android.support依赖项

关于如何解决它的任何想法?

小智 13

我按照官方指南也遇到了这个问题,请按照以下步骤进行修复。

在应用程序中添加 testImplementation build.gradle

// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.13.1'

testImplementation 'androidx.test:core-ktx:1.3.0'
testImplementation 'androidx.test.ext:junit-ktx:1.1.2'

// Robolectric environment
testImplementation 'org.robolectric:robolectric:4.4'

// Optional -- truth
testImplementation 'androidx.test.ext:truth:1.3.0'
testImplementation 'com.google.truth:truth:1.0'

// Optional -- Mockito framework
testImplementation 'org.mockito:mockito-core:3.3.3'
Run Code Online (Sandbox Code Playgroud)

官方指南错过了两个testImplementations

testImplementation 'androidx.test.ext:junit-ktx:1.1.2'

testImplementation 'org.robolectric:robolectric:4.4'
Run Code Online (Sandbox Code Playgroud)

testOptions在应用程序中添加块build.gradle

 android {
        // ...
        testOptions {
            unitTests.includeAndroidResources = true
        }
    }
Run Code Online (Sandbox Code Playgroud)

添加@RunWith(AndroidJUnit4::class)到您的测试类

例子:

import android.content.Context
import android.os.Build.VERSION_CODES.Q
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config

@RunWith(AndroidJUnit4::class)
@Config(sdk = [Q])
class UnitTestWithContextDemoTest {

    private val context: Context = ApplicationProvider.getApplicationContext()
    
    fun test_getPackageName() {
        assertThat(context.packageName).contains("your_package_name")
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记

@Config(sdk = [Q])当您targetSdkVersion大于29. 因为robolectric不支持targetSdkVersion大于29.


Arc*_*nes 12

我也遇到过这个问题.

如果你看一下这里迁移到Robolectric 4.0 ,建议在你的版本中添加以下行gradle.properties.

android.enableUnitTestBinaryResources=true
Run Code Online (Sandbox Code Playgroud)

问题是,如果你添加它,你gradle.properties将输出这个警告:

警告:选项设置'android.enableUnitTestBinaryResources = true'是实验性的,不受支持.

现在,如果你看看这里的 Robolectric版本.您可以看到这是一个已知的问题,他们说明了这一点

Android Gradle Plugin可能会报告以下警告,可以安全地忽略它:警告:选项设置'android.enableUnitTestBinaryResources = true'是实验性且不受支持的.Android Gradle Plugin 3.4将解决此问题.

我相信除非你能将你的gradle更新到3.4.您将无法解决此问题.

我所做的是将Robolectric 4.0作为依赖项.

testImplementation "org.robolectric:robolectric:4.0.2"
Run Code Online (Sandbox Code Playgroud)

并用.注释我的测试类

@RunWith(RobolectricTestRunner::class)
Run Code Online (Sandbox Code Playgroud)

这应该使您的测试工作.

现在,当您运行测试时,您会注意到Robolectric将记录以下内容:

[Robolectric]注意:不推荐使用旧资源模式; 见 http://robolectric.org/migrating/#migrating-to-40

现在忽略这一点,但只要你能更新你的gradle,就转移到新的Robolectric测试.

  • “最新的 gradle 版本”是什么意思?对于任何想知道他们是否确实需要更新或已经使用比您提到的版本更新的版本的人都会有帮助 (3认同)

Hot*_*ard 11

在类似问题上花费数小时,问题不在于依赖项,而在于 AndroidStudio 本身基于答案

IDE 尝试运行本地单元测试而不是检测

本地测试图标.

确保它作为插桩测试运行(红色是本地测试,绿色是插桩):

仪器测试图标

After added instrumented test for the class it's run as expected under instrumented. How I done this? 2 ways I found:

1) Edit configuration (as on the last screenshot) and adding function manually

2) Under Project tap (top left corner) I selected Tests instead of android, found the test, right click - create test. After this step all new tests are run under instrumented tests

  • 也许我对这一点的理解不正确。但是这个想法难道不是能够在 JVM 上运行测试而不使用 Android 框架吗? (6认同)

Bor*_*jev 5

我遇到了类似的错误,并且非常努力地修复它。我的问题是我正在混合AndroidJUnit4InstrumentationRegistry和版本/包。确保他们都是同一代的。这些是让这一切为我运行的课程:ApplicationProviderAndroidJUnitRunner

  • androidx.test.runner.AndroidJUnitRunner
  • androidx.test.platform.app.InstrumentationRegistry
  • androidx.test.ext.junit.runners.AndroidJUnit4
  • androidx.test.core.app.ApplicationProvider

dependencies对于这些,我在build.gradle 部分需要以下内容

androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:core:1.1.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation "com.android.support:support-annotations:27.1.1"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
Run Code Online (Sandbox Code Playgroud)

当然还有正确的

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Run Code Online (Sandbox Code Playgroud)

在我defaultConfigbuild.gradle


McB*_*dik 5

接下来的事情在谷歌测试指南中没有提到,但它们是我发现的:

  1. androidx.test如果单元测试只是一个接口/API(我不知道仪器测试怎么样),它需要实现,即 robolectric 库。这就是为什么还需要机器人依赖: testImplementation "org.robolectric:robolectric:{version}"
  2. @RunWith(AndroidJUnit4.class) 是必须的。要获得未弃用的类,您需要添加: testImplementation "androidx.test.ext:junit:{version}"。顺便说一下,这个依赖关系具有传递性 junit4 依赖关系。

您还可能面临:Failed to create a Robolectric sandbox: Android SDK 29 requires Java 9 (have Java 8)如果您使用java 8andcompileSdkVersion 29或以上。在这里您可以找到如何处理它。