読者です 読者をやめる 読者になる 読者になる

Spring Boot + kotlinでmockitoを使ってモック化したテストコードを書く

今回はkotlinでmockito使って処理をモック化したテストコードを書いてみた。

site.mockito.org

セットアップ

dependencies {
   ...

    testCompile "org.springframework.boot:spring-boot-starter-test"
    testCompile "org.mockito:mockito-core:$mockito_core_version"
    testCompile 'junit:junit:$junit_version'
}

※ mockitoは1.10.19を使いました。

モック化するクラス

  • Elasticsearchからデータを取得するサービスクラスを想定してモック化します。
  • 今回はモック化メインなのでElasticsearch側の処理は適当です。
interface ElasticsearchClient {
    fun foo() : String
}

@Service
class ElasticsearchClientImpl : ElasticsearchClient {
    override fun foo() : String {
        return "foo"
    }
}
  • foo()メソッドは"foo"を返すように実装しています。
  • このfoo()メソッドをコントローラーから呼び出し、コントローラーのテストでfoo()メソッドをモック化します。

テスト対象のコントローラー

@RestController
@EnableAutoConfiguration
@ComponentScan
@Api(description = "ヘルスチェック")
open class HealthCheckController constructor(val elasticsearchClient: ElasticsearchClient) {

    @ApiModel
    data class HealthCheck(
            @ApiModelProperty(required = true, value = "結果", example = "true")
            val result: Boolean,
            @ApiModelProperty(required = true, value = "ステータス", example = "OK")
            val status: String
    )

    @ApiOperation(value = "ヘルスチェック")
    @RequestMapping(value = "/health-check", method = arrayOf(RequestMethod.GET))
    fun index(): Response<HealthCheck> {
        return Response(HealthCheck(true, "OK"))
    }

    @ApiOperation(value = "ヘルスチェック")
    @RequestMapping(value = "/health-check/elasticsearch", method = arrayOf(RequestMethod.GET))
    fun elasticsearch(): Response<HealthCheck> {
        return Response(HealthCheck(true, elasticsearchClient.foo()))
    }
}
  • elasticsearch()ではfoo()メソッドを利用しています。
  • 運用時ではelasticsearch()はElasticsearchへリクエストを送信し正常に稼働しているかのヘルスチェックに利用します。
  • では、テストコードでfoo()メソッドをモック化します。

テストコード

@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration(classes = arrayOf(Application::class))
@WebAppConfiguration
class HealthCheckControllerTest {

    lateinit var mvc: MockMvc
    lateinit var elasticsearchClient: ElasticsearchClient
    lateinit var target: HealthCheckController

    @Before
    fun setup() {
        elasticsearchClient = Mockito.mock(ElasticsearchClient::class.java)
        target = HealthCheckController(elasticsearchClient)

        MockitoAnnotations.initMocks(this)
        mvc = MockMvcBuilders.standaloneSetup(target).build()
    }

    @Test
    fun testElasticsearch() {
        val type = Types.newParameterizedType(Response::class.java, HealthCheckController.HealthCheck::class.java)
        val adapter: JsonAdapter<Response<HealthCheckController.HealthCheck>> = Moshi.Builder().build().adapter(type)

        Mockito.`when`(elasticsearchClient.foo()).thenReturn("NG")

        val result: MvcResult = mvc.perform(get("/health-check/elasticsearch"))
                .andExpect(status().isOk()).andReturn()
        val response = adapter.fromJson(result.response.contentAsString)

        assertThat(response.value.result, Is.`is`(true))
        assertThat(response.value.status, Is.`is`("NG"))
    }
}
setup()メソッド
    @Before
    fun setup() {
        elasticsearchClient = Mockito.mock(ElasticsearchClient::class.java)
        target = HealthCheckController(elasticsearchClient)

        MockitoAnnotations.initMocks(this)
        mvc = MockMvcBuilders.standaloneSetup(target).build()
    }
  • 上記のコードでHealthCheckControllerのElasticsearchClientクラスインスタンスをモック化しています。
モック化はどこで?
Mockito.`when`(elasticsearchClient.foo()).thenReturn("NG")
  • 上記のコードでfoo()メソッドの返り値が"NG"になるようにしています。
        assertThat(response.value.result, Is.`is`(true))
        assertThat(response.value.status, Is.`is`("NG"))