julioribeiro
julioribeiro

Reputation: 1723

AndroidX : No instrumentation registered! Must run under a registering instrumentation

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?

Upvotes: 93

Views: 84645

Answers (17)

Pat Lee
Pat Lee

Reputation: 1658

In Android Studio's Run/Debug Configurations, make sure you are running your tests as Android Instrumented Tests (not JUnit).

Upvotes: 0

i30mb1
i30mb1

Reputation: 4786

For unitTest with Robolectric check your Test import annotation:

Should be

import org.junit.Test

Instead of

import org.junit.jupiter.api.Test

Upvotes: 0

crazygit
crazygit

Reputation: 489

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.2")

testImplementation ("androidx.test:core-ktx:1.5.0")
testImplementation ("androidx.test.ext:junit-ktx:1.1.5")

// Robolectric environment
testImplementation ("org.robolectric:robolectric:4.4")

// Optional -- truth
testImplementation ("androidx.test.ext:truth:1.5.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.5")

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.

Upvotes: 23

Moklesur Rahman
Moklesur Rahman

Reputation: 791

I know this is an old question. But I wanted to mention one thing If you are trying to test Android-related things and code write in the test folder. You will get this error too.

Android test src/androidtest and Pure unit test src/test

Upvotes: 1

Michael Troger
Michael Troger

Reputation: 3497

Definitely not the issue with the example of the OP but adding to the other answers for people finding this via a search engine:

A common issue when facing the same error as the OP happens when you are using JUnit 5 (Jupiter) next to JUnit 4 in your project and if you're mixing up the imports. Make sure that you imported

import org.junit.Test

from JUnit 4 and not

import org.junit.jupiter.api.Test

from JUnit 5. Robolectric only works with JUnit 4 at the time of writing

Upvotes: 0

hani
hani

Reputation: 51

For me, the problem was that service testing in Android should be done in its own scope. When you create an Android project, three packages are created in it: One is the main project The other is Android tests related to services and views written in front of it (androidTest). And the last package of other tests written in front of it (test).

I had to move my test to the androidtest folder and add the relevant dependencies via androidTestImplementation and don't forget that your libraries are of the same type to communicate with each other. And as a last note, you should use "@RunWith(AndroidJUnit4.class)" at the top of the test class

The related dependencies are as follows :

   androidTestImplementation 'androidx.test:core:(last version)'
   androidTestImplementation 'androidx.test:runner:(last version)'
   androidTestImplementation 'androidx.test:rules:(last version)'
   androidTestImplementation 'androidx.test.espresso:espresso-core:(last version)'
   androidTestImplementation 'androidx.test.espresso:espresso-intents:(last version)'

Upvotes: 0

ruhulamin choudhury
ruhulamin choudhury

Reputation: 18

[Note : To remember this ]

AndroidJUnit4.class | used to run testcases of intrumentation type inside source set called androidTest [which requires phone or emulator]

AndroidJUnit4ClassRunner | used to run testcases for local test inside source set called test folder. [ no phone /emulator required]

Exception or Improvement Case | Using Robo-electric and supported junit4 dependency, then AndroidJUnit4.class can be used inside test folder to test local test.

Use this dependency[try to add latest]

testImplementation "org.robolectric:robolectric:4.4"

Then in your test class, use @RunWith(AndroidJUnit4::class) Example : @RunWith(AndroidJUnit4::class)

-------For Reference-----

 @RunWith(AndroidJUnit4::class)

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

    }
}

Upvotes: 0

Patrick
Patrick

Reputation: 11

I got the same problem and here is how i fixed it:

  • move my test class to the "androidTest" package
  • annotate the test class with @RunWith(AndroidJUnit4.class)

Hope this can help

Upvotes: 1

qix
qix

Reputation: 7952

Looks like you forgot to annotate your TimeExtensionsUnitTest with @RunWith(AndroidJUnit4::class) re: https://github.com/android/android-test/issues/409. I can reproduce the error by commenting that out in my own tests.

That said, this is not the only way to get your error. I originally encountered it when I was updating some old Robolectric tests to use some AndroidX apis (http://robolectric.org/androidx_test/), including switching away from @RunWith(RobolectricTestRunner::class). In my case, I was trying to use a context in my @BeforeClass with ApplicationProvider.getApplicationContext<Context>(), which is wrong in AndroidX, even though it was ok using Roboletric's runner with appContext = RuntimeEnvironment.getApplication().applicationContextappContext. Fortunately I was able to move the logic into my @Before call to fix things without a significant hit.

More generally, I've noticed documentation out there isn't fully comprehensive all in one place explaining the migration from the very old android.support.test Android Testing Support Library and Roboletric dependencies to AndroidX, but here's some other notes:

  • If I want to run real instrumentation tests on an emulator/physical device, ensure that the tests are under src/androidTest. This also means I need to change in my build.gradle file the dependencies on androidx.test libraries from testImplementation => androidTestImplementation, and also explicitly set a testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" in the defaultConfig section. https://developer.android.com/training/testing/local-tests https://developer.android.com/training/testing/instrumented-tests
  • If I'm happy with using Robolectric to run those tests as local, I can keep them under src/test, declare the dependencies using testImplementation, and don't need the testInstrumentationRunner. It's nice that I don't have to change the code to do this since I'm using the AndroidX Test APIs, which Roboletric is compatible with as of v4.0.

Upvotes: 2

Sana Ebadi
Sana Ebadi

Reputation: 7220

in my case I was using getApplicationContext() in a fragment from the test package, I just change it to getContext(). and this fixed my crash!

Upvotes: 2

Andre Thiele
Andre Thiele

Reputation: 4201

Make sure to put your instrumentation tests (tests you run with a Runner) in androidTest and not just test

Upvotes: 3

Mesut GUNES
Mesut GUNES

Reputation: 7411

In my case, changing the test method name fixed the issue. Most probably the Android Studio cached the methods with indexes that caused a problem.

Upvotes: 0

McBodik
McBodik

Reputation: 753

Next things are not mentioned on google test guide, but they are what I found:

  1. 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}"
  2. @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.

Upvotes: 5

HotJard
HotJard

Reputation: 4818

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

Local tests icon.

Make sure it's run as instrumented test (red is local tests, green - instrumented):

Instrumented tests icon

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

Upvotes: 16

Archie G. Qui&#241;ones
Archie G. Qui&#241;ones

Reputation: 13708

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.

Upvotes: 35

tim4dev
tim4dev

Reputation: 2987

Simply check your import section:

import androidx.test.runner.AndroidJUnit4;

Upvotes: -4

Boris Strandjev
Boris Strandjev

Reputation: 46963

I had similar error and was struggling a lot to fix it. My problem was that I was mixing AndroidJUnit4, InstrumentationRegistry, ApplicationProvider and AndroidJUnitRunnerversions / 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

Upvotes: 5

Related Questions