MockKでString型のモックオブジェクトを生成しようとしたところ、以下のエラーが発生しました。
io.mockk.MockKException: Can't instantiate proxy for class kotlin.String
String型のモックオブジェクトが生成できないことを知らなかったので、スタックトレースを辿ったところ、
io.mockk.proxy.MockKAgentException: Failed to create proxy for class java.lang.String. class java.lang.String is one of excluded classes at io.mockk.proxy.jvm.ProxyMaker.throwIfNotPossibleToProxy
とあり、String型のモックオブジェクトを生成する過程で、ProxyMaker#throwIfNotPossibleToProxy()
内でMockKAgentException
がthrowされていました。
ProxyMaker#throwIfNotPossibleToProxy()
の処理内容を整理すると、以下のいずれかの条件を満たすときにモックオブジェクトが生成できないことが分かりました。
- 1.モック対象のオブジェクトが以下のいずれかの型である
- プリミティブ型 および それらのラッパークラス
- String型
- Void型
- Class型
- 2.モック対象のオブジェクトが任意の型の配列である
- 3.モック対象のオブジェクトが以下のすべての条件を満たす
最後の条件が少し分かりづらいですが、以下のようなコードを書くとMockKAnnotations.init(this)
の時点でMockKAgentException
がthrowされます。
import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.AdditionalInterface import io.mockk.impl.annotations.MockK import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test class SampleClass { fun hoge(): String = "hoge" } interface SampleInterface { fun fuga(): String } class SampleTest { @MockK @AdditionalInterface(SampleInterface::class) private lateinit var sample: SampleClass @BeforeEach fun beforeEach() { MockKAnnotations.init(this) } @Test fun test() { every { sample.hoge() } returns "[override] hoge" every { (sample as SampleInterface).fuga() } returns "[implementation] fuga" ... } }
参考
- https://github.com/mockk/mockk/blob/37fc4c858edfadee07d1a3883cdb7616c5af379f/agent/jvm/src/main/kotlin/io/mockk/proxy/jvm/ProxyMaker.kt#L122-L137
- https://github.com/mockk/mockk/blob/37fc4c858edfadee07d1a3883cdb7616c5af379f/agent/jvm/src/main/kotlin/io/mockk/proxy/jvm/ProxyMaker.kt#L172-L183
- https://github.com/mockk/mockk/blob/284da25e0f6df8b291b356cde14980a8a4529073/mockk/jvm/src/main/kotlin/io/mockk/junit5/MockKExtension.kt#L77-L81