AndroidX : No instrumentation registered! Must run under a registering instrumentation
Solution 1
Update
You should no longer encounter this error if youre using the latest gradle version.
I also encountered this issue.
If you look at migrating to Robolectric 4.0 here, it suggest to add the following line in your gradle.properties
.
android.enableUnitTestBinaryResources=true
The problem is that, if you add this you your gradle.properties
, it will output this warning:
WARNING: The option setting 'android.enableUnitTestBinaryResources=true' is experimental and unsupported.
Now, if you look at Robolectric releases here. You could see that this is a known issue where they state that
Android Gradle Plugin may report the following warning, which may be safely ignored: WARNING: The option setting 'android.enableUnitTestBinaryResources=true' is experimental and unsupported.. Android Gradle Plugin 3.4 will resolve this issue.
I believe unless you could update you gradle to 3.4. You won't be able to solve this issue.
What I did instead was to include Robolectric 4.0 as dependency.
testImplementation "org.robolectric:robolectric:4.0.2"
and annotate my test class with
@RunWith(RobolectricTestRunner::class)
This should make your test work.
Now when you run the test, you'll notice that Robolectric will log the following:
[Robolectric] NOTICE: legacy resources mode is deprecated; see http://robolectric.org/migrating/#migrating-to-40
Ignore this for now but as soon as you could update your gradle, migrate to the new Robolectric testing.
Solution 2
I follow the official guide also met this issue, fix it with below steps.
Add testImplementation in app 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'
The official guide missed two testImplementations
testImplementation 'androidx.test.ext:junit-ktx:1.1.2'
testImplementation 'org.robolectric:robolectric:4.4'
Add testOptions
block in app build.gradle
android {
// ...
testOptions {
unitTests.includeAndroidResources = true
}
}
Add @RunWith(AndroidJUnit4::class)
to your test class
Example:
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")
}
}
NOTE
@Config(sdk = [Q])
is required when your targetSdkVersion
greater than 29
. Because robolectric
NOT support targetSdkVersion
greater than 29
.
Solution 3
Spend hours on similar issue, and the problem wasn't in dependencies, rather in AndroidStudio itself Based on the answer:
IDE tries to run local unit tests instead of instrumented
Make sure it's run as instrumented test (red is local tests, green - instrumented):
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
Solution 4
I had similar error and was struggling a lot to fix it. My problem was that I was mixing AndroidJUnit4
, InstrumentationRegistry
, ApplicationProvider
and AndroidJUnitRunner
versions / packages. Make sure they all are of the same generation. These are the classes that made it all run for me:
androidx.test.runner.AndroidJUnitRunner
androidx.test.platform.app.InstrumentationRegistry
androidx.test.ext.junit.runners.AndroidJUnit4
androidx.test.core.app.ApplicationProvider
for these I needed the following in the dependencies
part of my 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'
And of course the correct
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
in my defaultConfig
of the build.gradle
Solution 5
Next things are not mentioned on google test guide, but they are what I found:
-
androidx.test
in case of unit tests is just an interface/api (I don't know what about instrumented tests) and it needs implementations, which is robolectric library. That's why robolectric dependency is also required:testImplementation "org.robolectric:robolectric:{version}"
-
@RunWith(AndroidJUnit4.class)
is required. To get nondeprecated class you need to add:testImplementation "androidx.test.ext:junit:{version}"
. By the way this dependency has transitive junit4 dependensy.
Also you can faced with: Failed to create a Robolectric sandbox: Android SDK 29 requires Java 9 (have Java 8)
in case you use java 8
and compileSdkVersion 29
or above. Here you can find how to deal with it.
julioribeiro
Updated on July 05, 2022Comments
-
julioribeiro almost 2 years
I'm trying to run a local unit test that depends on the context, and was following this guide: https://developer.android.com/training/testing/unit-testing/local-unit-tests#kotlin and I set up my project like this (following this link : 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' }
My espresso_version is espressoVersion = '3.1.0'
My test that is located in module-name/src/test/java/ looks like this:
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) { } } } }
Everytime I run it, it gives me:
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)
If I run it as a Instrumental Test(changing the package) it runs without errors. But I thought that this guide was exactly to be able to run unit test using Android Framework classes such as Context. I even tried run that
class UnitTestSample
but the same error occurs.I also removed all android.support dependencies from my project
Any ideas on how to solve it?
-
Jeremy Harris over 5 yearsWhile this may be an answer, it is good practice to add more details to your answer to help OP and future readers. Code only answers are generally discouraged.
-
Brian Reinhold almost 5 yearsI would agree with Boris. I spent more than 12 hours trying to resolve that problem. I had a set of working instrumented tests using the android.support.test and I was hesitant to change that. When I needed to test a service, it seemed I had to go with androidx,test. Out of desperation I went back and changed android.support.test to androidx.test and the method InstrumentationRegistry.getTargetContext() to InstrumentationRegistry.getInstrumentation().getTargetContext() and FINALLY that error went away and the other tests still ran (sigh of relief).
-
Jonathan Persgarden almost 4 yearsMaybe I understand this incorrectly. But isn't the idea to be able to run the tests on the JVM without using the Android framework?
-
Hoàng Tùng over 3 yearsIt gives the error "error: <identifier> expected @RunWith(RobolectricTestRunner::class)"
-
arekolek over 2 yearsWhat version do you mean by the
latest gradle version
? Would be helpful for anybody wondering if they actually need to update or already use a version newer than what you referred to