AndroidX:未注册任何工具!必须在注册工具下运行

时间:2018-12-03 14:29:35

标签: 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'
}

我的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) {
            }
        }
    }
}

每次运行它,它都会给我:

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)

如果我将其作为仪器测试(更改程序包)运行,则运行不会出错。 但是我认为该指南完全能够使用Android Framework类(例如Context)运行单元测试。 我什至尝试运行该class UnitTestSample,但发生相同的错误。

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

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

8 个答案:

答案 0 :(得分:9)

我也遇到了这个问题。

如果您打算迁移到Robolectric 4.0 here,建议您在gradle.properties中添加以下行。

android.enableUnitTestBinaryResources=true

问题是,如果您将此添加到gradle.properties中,它将输出以下警告:

  

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

现在,如果您查看Robolectric版本here。您可能会看到这是一个已知问题,他们指出了这一点

  

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

我相信除非您可以将gradle更新为3.4。您将无法解决此问题。

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

testImplementation "org.robolectric:robolectric:4.0.2"

并用

注释我的测试班
@RunWith(RobolectricTestRunner::class)

这应该使您的测试有效。

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

  

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

暂时忽略此信息,但是一旦您可以更新gradle,请迁移到新的Robolectric测试。

答案 1 :(得分:0)

我有类似的错误,正在努力解决。我的问题是我混用了AndroidJUnit4InstrumentationRegistryApplicationProviderAndroidJUnitRunner版本/软件包。确保它们都是同一代人。这些是使它们全部运行的类:

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

为此,我需要在build.gradle的dependencies部分中进行以下操作

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'

当然是正确的

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

在我的defaultConfig的{​​{1}}中

答案 2 :(得分:0)

在类似问题上花费几个小时,问题不在于依赖关系,而在于基于answer的AndroidStudio本身:

IDE尝试运行本地单元测试而不是使用仪器

Local tests icon

确保它已作为检测测试运行(红色是本地测试,绿色-已检测):

Instrumented tests icon

在为该类添加了检测测试之后,它会在检测条件下按预期运行。我是怎么做到的?我找到了2种方法:

1)编辑配置(如上图所示)并手动添加功能

2)在“项目”点击下(左上角),我选择了Tests而不是android,找到了测试,右键单击-创建测试。完成此步骤后,所有新测试都将在已测试的测试下运行

答案 3 :(得分:0)

谷歌测试指南中未提及以下内容,但这是我发现的内容:

    在单元测试的情况下,
  1. androidx.test只是一个接口/ api(我不知道仪器测试如何),它需要实现,它是robolectric库。 这就是为什么还需要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 8或更高版本,您还可能会遇到compileSdkVersion 29Here,您可以找到处理方法。

答案 4 :(得分:0)

我遵循official guide也遇到了此问题,请按照以下步骤进行修复。

在应用build.gradle中添加testImplementation

// 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'

official guide错过了两个testImplementations

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

testImplementation 'org.robolectric:robolectric:4.4'

在应用testOptions中添加build.gradle

 android {
        // ...
        testOptions {
            unitTests.includeAndroidResources = true
        }
    }

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

注意

当您的@Config(sdk = [Q])大于targetSdkVersion时,需要

29。因为robolectric不支持大于targetSdkVersion的{​​{1}}。

答案 5 :(得分:0)

就我而言,更改测试方法名称解决了该问题。 很可能是 Android Studio 使用导致问题的索引缓存了方法。

答案 6 :(得分:0)

确保将您的仪器测试(使用 Runner 运行的测试)放在 androidTest 中,而不仅仅是测试

答案 7 :(得分:-1)

只需检查您的导入部分:

import androidx.test.runner.AndroidJUnit4;