2
votes

I want to shadow a Kotlin companion object. The companion object what i want to shadowing is:

class MyLogClass {
    companion object {
        
        @JvmStatic
        fun logV(tag: String, messageProvider: () -> String) {
            if (SPUtils.getLogLevel() >= mLogLevel) {
                Log.v(tag, messageProvider.invoke())
            }
        }
    }
}

What I have tried:

// Shadow class...
@Implements(MyLogClass.Companion::class)
class ShadowMyLogClass {

    @Implementation
    fun v(tag: String, messageProvider: () -> String) {
        redirectConsole(tag, messageProvider)
    }

    private fun redirectConsole(tag: String, messageProvider: () -> String) {
        println("[$tag]${messageProvider.invoke()}")
    }
}

// And in Testing class...
class TestMyLogClass {
    @Test
    fun test() {
        MyLogClass.logV("some tag") {
            "some message"
        }
    }
}

But what I have tried occur an Error:

Caused by: java.lang.IllegalAccessError: tried to access class kotlin.jvm.internal.DefaultConstructorMarker from class com.example.zspirytus.log.impl.MyLogClass$Companion

It seems that there is lost an constructor method which type is DefaultConstructorMarker, How can I make an DefaultConstructorMarker or other way to create a Shadow MyLogClass? Thanks for your reading and answers!

1

1 Answers

1
votes

Here's what I did to shadow a method in the companion object

@Implements(Object::class)
class ShadowObject {
  companion object {
    @Implementation
    @JvmStatic
    fun verify(): Boolean {
      return true
    }
  }
}

Use:

@RunWith(AndroidJUnit4::class)
@Config(shadows = [
  ShadowObject::class
])
class UserTest {
  // Rest of testing class
}

In your case, I'd say you just need to wrap your @Implementation method with companion object, and change @Implements(MyLogClass.Companion::class) to just @Implements(MyLogClass::class)