没有注册的测试仪器! 必须在注册的测试仪器下运行

我试图运行一个依赖于上下文的本地单元测试,并遵循以下指南: https://developer.android.com/training/testing/unit-testing/local-unit-tests#kotlin和我像这样设置我的项目(以下链接: https://developer.android.com/training/testing/set-up-project) :

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

我的浓缩咖啡版本是 EspressoVersion =’3.1.0’

我在 < em > 模块名/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)

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

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

有办法解决吗?

58017 次浏览

更新

如果您使用的是最新的 gradle 版本,则不会再遇到此错误。


我也遇到了这个问题。

如果考虑迁移到 Robolectric4.0 给你,建议在 gradle.properties中添加以下代码行。

android.enableUnitTestBinaryResources=true

问题是,如果你把它加到你的 gradle.properties上,它会输出这个警告:

警告: 选项设置 ‘ android.ableUnitTestBinaryResources = true’是实验性的,而且 无依无靠。

现在,如果你看机器电气发布 给你。你可以看到,这是一个众所周知的问题,他们声明

Android Gradle Plugin 可能会报告以下警告,这些警告可能会被安全地忽略: 警告: 选项设置‘ Android.ableUnitTestBinaryResources = true’是实验性的,不受支持。.Android Gradle Plugin 3.4将解决这个问题。

我相信除非你能升级到3.4级,否则你不可能解决这个问题。

相反,我所做的是将 Robolectic 4.0作为依赖项包含进来。

testImplementation "org.robolectric:robolectric:4.0.2"

注释我的测试类

@RunWith(RobolectricTestRunner::class)

这应该能让你的测试成功。

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

[ Robolectic ]注意: 遗留资源模式已弃用; 请参阅 Http://robolectric.org/migrating/#migrating-to-40

暂时忽略这一点,但一旦你可以更新你的等级,迁移到新的机器电子测试。

我也有过类似的错误,并且很努力地去修复它。我的问题是我混合了 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"

在我的 defaultConfigbuild.gradle

只需检查您的进口部分:

import androidx.test.runner.AndroidJUnit4;

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

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

Local tests icon.

确保它作为检测测试运行(红色代表本地测试,绿色代表检测测试) :

Instrumented tests icon

在为类添加了检测测试之后,它将按照预期的方式在检测下运行。我是怎么做到的?我发现了两种方法:

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

2)在项目点击(左上角)我选择测试代替 android,找到测试,右击-创建测试。在此步骤之后,所有新测试都在检测测试下运行

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

  1. 在单元测试的情况下,androidx.test只是一个接口/api (我不知道什么是插装测试) ,它需要实现,这是一个机器电子库。 这就是为什么机器电依赖也是必需的: testImplementation "org.robolectric:robolectric:{version}"
  2. 要获得不推荐的类,需要添加: 顺便说一下,这个依赖项具有传递的 junit4依赖项。

也可以面对: Failed to create a Robolectric sandbox: Android SDK 29 requires Java 9 (have Java 8)的情况下,你使用 java 8compileSdkVersion 29或以上。你可以找到如何处理它。

我按照 官方指南也遇到了这个问题,用下面的步骤解决它。

在应用程序 build.gradle中添加 test 实现

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

官方指南漏掉了两个测试实现

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


testImplementation 'org.robolectric:robolectric:4.4'

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

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

注意

targetSdkVersion大于 29时需要 @Config(sdk = [Q])。因为 robolectric不支持 targetSdkVersion大于 29

在我的例子中,更改测试方法名称修复了这个问题。 很可能是 Android Studio 缓存了带有引起问题的索引的方法。

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

[注意: 要记住这一点]

Class | 用于在名为 androidTest 的源代码集内运行插入类型的测试用例(它需要电话或模拟器)

AndroidJUnit4ClassRunner | 用于在名为 test file 的源集内运行本地测试的测试用例

例外或改进案例 | 使用机器电子和支持 junit4依赖,然后 AndroidJUnit4.class 可以用于测试文件夹内测试本地测试。

使用这个依赖项[尝试添加最新版本]

Test 实现“ org.robolecric: robolecric: 4.4”

然后在测试类中使用@RunWith (AndroidJUnit4: : class) 示例:@RunWith (AndroidJUnit4: : class)

——供参考——

@ RunWith (AndroidJUnit4: : class)

类 TasksViewModelTest {

@Test
fun addNewTask_setsNewTaskEvent() {


// Given a fresh TasksViewModel
var tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())


// When adding a new task
tasksViewModel.addNewTask()


// Then the new task event is triggered


}

}

在我的例子中,我在测试包的一个片段中使用了 getApplicationContext(),我只是将它改为 getContext()。这个修好了我的车祸!

看起来你忘记用 @RunWith(AndroidJUnit4::class) re: https://github.com/android/android-test/issues/409注释你的 TimeExtensionsUnitTest了。我可以通过在自己的测试中注释掉这个错误来重现这个错误。

也就是说,这不是你犯错误的唯一方法。我最初遇到它时,我正在更新一些旧的机器人测试使用一些 AndroidXapis(http://robolectric.org/androidx_test/) ,包括从 @RunWith(RobolectricTestRunner::class)切换。在我的情况下,我试图 在我的 @BeforeClass中使用上下文ApplicationProvider.getApplicationContext<Context>()这在安卓系统中是错误的,即使它是确定使用机器人的运动员与 appContext = RuntimeEnvironment.getApplication().applicationContextappContext。幸运的是,我能够将逻辑转移到我的 @Before调用中来修复问题,而不会造成重大损失。

更一般地说,我注意到那里的文档没有完全全面地解释从非常老的 android.support.test Android 测试支持库和机器人依赖到 Android X 的迁移,但是这里有一些其他的注意事项:

  • 如果我想在模拟器/物理设备上运行真正的检测测试,请确保测试在 src/androidTest之下。这也意味着我需要在 build.gradle文件中从 testImplementation = > androidTestImplementation更改对 androidx.test库的依赖关系,并在 defaultConfig部分中显式设置 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"Https://developer.android.com/training/testing/local-tests Https://developer.android.com/training/testing/instrumented-tests
  • 如果我喜欢使用 Robolecric 作为本地运行这些测试,我可以将它们保持在 src/test下,使用 testImplementation声明依赖项,而不需要 testInstrumentationRunner。由于我使用的是 AndroidX Test API,Roboleric 在 v4.0时与之兼容,因此不必修改代码就可以完成这项工作。

我也有同样的问题,我是这样解决的:

  • 将我的测试类移动到“ 机器人测试”包
  • @ RunWith (AndroidJUnit4.class)注释测试类

希望这个能帮上忙