はじめに
SpringTestにてmockito-kotlinを使用してテスト対象クラスから呼び出しているクラスをMock化したい時の記述例のメモです。
登場人物
あくまでも例です。
実在の人物や団体などとは関係ありません。
- mock対象のクラス
@Component
class MockTargetClass(
externalApiClient : ExternalApiClient
) {
fun connectExternalApi() : ApiResult {
return externalApiClient.connect()
}
}
- test対象のクラス
@Service
class TestTargetClass(
mockTargetClass : MockTargetClass
) {
fun getExternalApiConnection() : String {
return mockTargetClass.connectExternalApi().connectionStatus
}
}
- testクラス(Mock導入前)
@SpringBootTest
class TestClass {
@Autowired
lateinit var testTargetClass : TestTargetClass
@Test
fun connectionTest() {
val result = testTargetClass.getExternalApiConnection()
assertEquals("OK", result)
}
@Test
fun disconnectionTest() {
...
}
...
}
- build.gradle.kts
build.gradle.kts
dependencies {
...
testImplementation("org.mockito.kotlin:mockito-kotlin:3.1.0")
}
テスト環境では外部APIの接続で落ちるとします。
Mock記述例
@SpringBootTest
class TestClass {
@Autowired
lateinit var testTargetClass : TestTargetClass
@MockBean
lateinit var mockTargetClass : MockTargetClass
@BeforeEach
init() {
whenever(MockTargetClass.connectExternalApi(any())).doReturn(ApiResult.ok))
}
@Test
fun connectionTest() {
val result = testTargetClass.getExternalApiConnection()
assertEquals("OK", result)
}
@Test
fun disconnectionTest() {
...
}
...
テストクラス(TestClass
)から直接Mock対象クラスを呼び出していなくても、アノテーション(@MockBean
)でMock化したクラスを後からインジェクションできます。
@Mock
アノテーションを使用するよりもすっきり書けるかと思います。
init()
関数でMock化したクラスの挙動を定義しています。
void型関数をMockして何もしないようにしたいという要求にはどうするの?と思われるかもしれませんが、@MockBean
でインジェクションされたMockクラスのvoid関数はデフォルトで何もしない関数に置き換わるようです。