24

I try to run Kotlin instrumentation tests for android.

In my app/build.gradle:

    android {
        dataBinding {
            enabled = true
        }
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.myproject"
            minSdkVersion 18
            targetSdkVersion 28
            versionCode 6
            versionName "0.0.7"
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }

        sourceSets {
            main.java.srcDirs += 'src/main/kotlin'
            androidTest.java.srcDirs += 'src/androidTest/kotlin'
        }

androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:rules:1.1.2-alpha02'
    androidTestImplementation 'androidx.test:runner:1.1.2-alpha02'

In folder /app/src/androidTest/kotlin/com/myproject/ I has Kotlin test:

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import org.junit.Rule
import org.junit.runner.RunWith

import androidx.test.rule.ActivityTestRule
import com.myproject.ui.activity.TradersActivity
import org.junit.Before


@RunWith(AndroidJUnit4::class)
@SmallTest
class TradersActivityTest {

    private lateinit var stringToBetyped: String

    @get:Rule
    var activityRule: ActivityTestRule<TradersActivity> = ActivityTestRule(TradersActivity::class.java)

    @Before
    fun initValidString() {
        // Specify a valid string.
        stringToBetyped = "Espresso"
    }

}

but when I run test I get error:

$ adb shell am instrument -w -r   -e debug false -e class 'com.myproject.TradersActivityTest' com.myproject.debug.test/androidx.test.runner.AndroidJUnitRunner
Client not ready yet..
Started running tests

java.lang.RuntimeException: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded.
at androidx.test.ext.junit.runners.AndroidJUnit4.throwInitializationError(AndroidJUnit4.java:92)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:82)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:51)
at androidx.test.ext.junit.runners.AndroidJUnit4.<init>(AndroidJUnit4.java:46)
at java.lang.reflect.Constructor.newInstance(Native Method)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at androidx.test.internal.runner.junit4.AndroidAnnotatedBuilder.runnerForClass(AndroidAnnotatedBuilder.java:63)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at androidx.test.internal.runner.AndroidRunnerBuilder.runnerForClass(AndroidRunnerBuilder.java:153)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at androidx.test.internal.runner.TestLoader.doCreateRunner(TestLoader.java:73)
at androidx.test.internal.runner.TestLoader.getRunnersFor(TestLoader.java:104)
at androidx.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:789)
at androidx.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:544)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:387)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1879)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:72)
... 16 more
Caused by: org.junit.runners.model.InitializationError
at org.junit.runners.ParentRunner.validate(ParentRunner.java:418)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:43)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:48)
... 18 more

Tests ran to completion.
Alexei
  • 14,350
  • 37
  • 121
  • 240

11 Answers11

21

I faced this problem in kotlin , used below code and it worked

@RunWith(AndroidJUnit4::class)

@LargeTest

class MainActivityTest {

    private val TAG = "MainActivityTest"

    @get:Rule
    val activityRule = ActivityTestRule(MainActivity::class.java)
}

follow the link below:- https://developer.android.com/training/testing/junit-rules

user1035292
  • 1,378
  • 12
  • 14
12

The error message displayed when I delete the @Test method.

You can try to put a @Test method and run

@Test
public void signInTest() {


}
JackWu
  • 1,036
  • 1
  • 12
  • 22
  • that was my problem – Nauman Ash Oct 11 '19 at 06:17
  • 16
    This answer does not make any sense. When you remove the test method, then there are no more tests to run, therefore it works. But that's not the point. – Alexander Pacha Jan 29 '20 at 09:41
  • @AlexanderPacha You've got it backwards -- they're saying that you need to *add* a test method to get it to work. This was, in fact, my silly little problem. I forgot to annotate my methods with `@Test`. You'll see this error if you have no `@Test`-annotated methods. – Greyson Parrelli Jan 14 '22 at 15:05
8

For those who still have problems like this, This happens because Kotlin compiler wants to generate getter/setter properties. for example, I've got this error because I didn't mention @Rule annotation with @get:Rule.

If we annotate properties like this with @get:... or @JvmField it could solve the problem.

@get:Rule
var mActivityRule = ActivityTestRule(MainActivity::class.java)

Or

@Rule
@JvmField
var mActivityRule = ActivityTestRule(MainActivity::class.java)

@JvmField instructs the Kotlin compiler not to generate getters/setters for this property and expose it as a field.

FarshidABZ
  • 3,860
  • 4
  • 32
  • 63
7

In regards to @RunWith(AndroidJUnit4::class)

Delete

import androidx.test.ext.junit.runners.AndroidJUnit4

Use

import androidx.test.runner.AndroidJUnit4
Max Kilzieh
  • 161
  • 1
  • 8
  • Did not work for me. Also, the androidx.test.runner.AndroidJUnit4 is deprecated. Source: https://developer.android.com/reference/androidx/test/runner/AndroidJUnit4 – lubrum Feb 27 '22 at 22:21
  • It wasn't depreciated at the time of writing, but thanks for your comment. Others, please find an ALTERNATIVE workaround as this is depreciated. Thanks to Luciano for finding out. – Max Kilzieh Feb 28 '22 at 08:35
2

I just wasted all day on this issue

I'm guessing you are using the multiplatform plugin like I am.

I was about to give up on trying to moving my instrumented tests to src/androidTest/kotlin instead of src/androidTest/java

when I decided to log kotlin.sourcesets.names, which printed

[androidAndroidTest, androidAndroidTestDebug, androidDebug, androidMain, androidRelease, androidTest, androidTestDebug, androidTestRelease, commonMain, commonTest, iosArm32Main, iosArm32Test, iosArm64Main, iosArm64Test, iosX64Main, iosX64Test, macosX64Main, macosX64Test]

Soo I realized in order for dependencies to resolve correctly I needed to change

androidTestImplementation -> androidAndroidTestImplementation
testImplementation -> androidTestImplementation

They don't describe this in the documentation of course. (as far as I have found)

... so for example, for you, I think the dependencies for your instrumented test dependencies should be:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'

not

androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'

lnstadrum
  • 550
  • 3
  • 15
luca992
  • 1,548
  • 22
  • 27
2

I got this error when I have some parameters in my test method. So, if you have it - delete it.

@Test
fun someTestMethod(someParams: Int) { // delete method params
    assert(1==1)
}
nutella_eater
  • 3,393
  • 3
  • 27
  • 46
  • This was it for me - more generally, if the signature of a test was incorrect I received this error. I bumped into this testing coroutines where I omitted the `` on the example below. `fun testSuspendFunction() = runBlocking {}` – Edward Woolhouse Jul 08 '20 at 12:29
2

just make sure that if your test is calling any suspend methods, you run your test with runBlocking{}. Solved the problem for me

2

Max Kilzieh answer worked for me Using import androidx.test.runner.AndroidJUnit4 instead of import androidx.test.ext.junit.runners.AndroidJUnit4

Imron Gamidli
  • 91
  • 1
  • 7
1

You don't have any functions annotated with @Test. This is likely the cause of the issue. I've run my own test using the AndroidJUnit4 runner on a class without @Test functions, and reconstructed this behavior.

The AndroidJUnit4 JUnit4 runner is the cause of this issue, and despite its attempt to provide a detailed message (see the code where the exception is thrown), it gives you a wrong message.

The following are more ways to achieve this error:

@Test
fun willThrowInitializationErrorBecauseReturnsNonUnitValue(): Int {
    return 0
}

@Test
fun willThrowInitializationErrorBecauseTakesParameters(param: Int) {
}

The error is generated by the fact that you're writing JUnit4 style tests, and they're expected to conform to JUnit4 semantics, but it would be nice if the error message were more clear.

To make matters worse, if one test function is messed up the runner won't run any tests because the InitializationError is thrown in the constructor of the AndroidJUnit4 class.

fsryan
  • 11
  • 1
0

In My case while using Java,I faced issue when I did below mistakes.

1)I had made ActivityTestRule as private.

  All test cases should be public always.

2)I didn't add static for BeforeClass and AfterClass methods

  Methods of @BeforeClass and @AfterClass should be static

  Ex)@BeforeClass
     public static void setUp(){

     }
Tarun Anchala
  • 2,232
  • 16
  • 15
0

Also just to expand on the answers, but it won't help for this particular reason:

If you use kotlin and get this while testing, make sure you aren't using suspend in DAO.

(Sorry to put it here, there was no thread with this in kotlin and I already found the solution so it might help someone)