1

I'm trying to create a trait for Android's InstrumentationTestCase that contains an abstract property and a method that uses this property. Unfortunately when I run this test it crashes with a java.lang.VerifyError. So here's a code sample that causes the crash:

trait ExtendedInstrumentationTestCase : InstrumentationTestCase {
    val string: String

    fun printString(): Unit {
        println(string)
    }
}

class MyApplicationTestCase :
        ApplicationTestCase<Application>(javaClass<Application>()),
        ExtendedInstrumentationTestCase {

    override val string: String = "test"

    override fun setUp() {
        super<ApplicationTestCase>.setUp()

        printString()
    }

    override fun tearDown() {
        super<ApplicationTestCase>.tearDown()
    }
}

And that's what I get from the logcat:

W/dalvikvm﹕ VFY: Lcom/kotlintest/MyApplicationTestCase; is not instance of Landroid/test/InstrumentationTestCase;
W/dalvikvm﹕ VFY: bad arg 0 (into Landroid/test/InstrumentationTestCase;)
W/dalvikvm﹕ VFY:  rejecting call to Lcom/kotlintest/ExtendedInstrumentationTestCase$$TImpl;.printString (Landroid/test/InstrumentationTestCase;)V
W/dalvikvm﹕ VFY:  rejecting opcode 0x71 at 0x0000
W/dalvikvm﹕ VFY:  rejected Lcom/kotlintest/MyApplicationTestCase;.printString ()V
W/dalvikvm﹕ Verifier rejected class Lcom/kotlintest/MyApplicationTestCase;
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb1e90648)
E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.VerifyError: com/kotlintest/MyApplicationTestCase
            at java.lang.Class.getDeclaredConstructors(Native Method)
            at java.lang.Class.getConstructors(Class.java:459)
            at android.test.suitebuilder.TestGrouping$TestCasePredicate.hasValidConstructor(TestGrouping.java:228)
            at android.test.suitebuilder.TestGrouping$TestCasePredicate.apply(TestGrouping.java:217)
            at android.test.suitebuilder.TestGrouping$TestCasePredicate.apply(TestGrouping.java:213)
            at android.test.suitebuilder.TestGrouping.select(TestGrouping.java:172)
            at android.test.suitebuilder.TestGrouping.selectTestClasses(TestGrouping.java:162)
            at android.test.suitebuilder.TestGrouping.testCaseClassesInPackage(TestGrouping.java:156)
            at android.test.suitebuilder.TestGrouping.addPackagesRecursive(TestGrouping.java:117)
            at android.test.suitebuilder.TestSuiteBuilder.includePackages(TestSuiteBuilder.java:102)
            at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:366)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4435)
            at android.app.ActivityThread.access$1300(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

And when I make the printString() method an extension method my tests start working:

trait ExtendedInstrumentationTestCase : InstrumentationTestCase {
    val string: String
}

fun ExtendedInstrumentationTestCase.printString(): Unit {
    println(string)
}

As far as I understand the bug is in Dalvik, but I'd like to known exactly where the bug is, why it happens and how I can change the first version of my trait to make this code work.

1
  • These bugs were reported in YouTrack as fixed. Commented Dec 30, 2015 at 21:51

1 Answer 1

4

This is a bug in Kotlin compiler: KT-3006.

The problem is you're inheriting from a trait which requires a class, without invoking the superclass' constructor. Compiler incorrectly allows this and it blows up later at runtime.

The correct fix would be to invoke InstrumentationTestCase's constructor explicitly:

class MyApplicationTestCase :
        ApplicationTestCase<Application>(javaClass<Application>()),
        ExtendedInstrumentationTestCase,
        InstrumentationTestCase() {
...
Sign up to request clarification or add additional context in comments.

4 Comments

thank you! Seems that the bug is really in the Kotlin compiler, but the problem is even worse. I've just noticed that ApplicationTestCase is not a subclass of InstrumentationTestCase, so it must be not allowed to inherit from this trait in this case.
I found a bug on this behavior: KT-1963.
Actually these two bugs are the same one, so I've merged them. Sorry if this wasn't clear at first: yes, your original code shouldn't be allowed by the compiler. Every trait requirement must be satisfied in each subclass, but the compiler doesn't check that at the moment
These bugs were reported in YouTrack as fixed, so this is no longer an issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.