Kotlinのテストツール活用例!JUnit 5・Mockito Kotlin・MockKで単体テストを書く方法
生徒
「Kotlinでコードを書けるようになってきたのですが、正しく動いているか毎回手で確認するのが大変です。」
先生
「その悩みを解決するのがテストツールです。KotlinではJUnit 5、Mockito Kotlin、MockKなどを使うと、関数やクラスの動きを自動で確認できます。」
生徒
「JUnitとMockitoは名前を聞いたことがあります。Kotlinでもそのまま使えるんですか?」
先生
「使えます。ただしKotlinにはnull安全、final class、コルーチンなどの特徴があるので、Javaのテストと同じ感覚だけでは足りない場面もあります。実務で使いやすい形で見ていきましょう。」
1. Kotlinでテストツールを使う目的とJUnit・Mockitoの役割
Kotlinのテストツールは、作成した関数やクラスが期待どおりに動くかを自動で確認するために使います。画面を開いてボタンを押すような手作業の確認だけに頼ると、修正のたびに確認漏れが起きやすくなります。そこで、単体テストを書いておくと、コード変更後に同じ確認を何度でも実行できます。
JUnit 5は、Kotlinのテストコードを実行するための基本ツールです。@Testを付けた関数をテストとして実行し、assertEqualsなどで結果を確認します。Mockito Kotlinは、データベースや外部APIの代わりになる偽物の部品、つまりモックを作るために使います。
たとえば、消費税込み価格を計算する関数を作った場合、毎回手で計算するよりも、JUnitで期待値を固定して確認する方が安全です。さらに、ユーザー情報をDBから取得するような処理では、MockitoやMockKでDBの代わりを用意すると、テスト用DBを準備しなくてもロジックを確認できます。
- JUnit 5:テストの実行、期待値の検証、例外テストに使う
- Mockito Kotlin:RepositoryやAPIクライアントをモック化する
- MockK:Kotlinのfinal class、object、コルーチンに強いモックツール
- Gradle:テスト依存関係の管理とテストコマンドの実行に使う
2. GradleでJUnit 5とMockito Kotlinを導入する設定
KotlinでJUnit 5やMockito Kotlinを使うには、まずbuild.gradle.ktsにテスト用ライブラリを追加します。KotlinプロジェクトではGradle Kotlin DSLを使うことが多いため、設定ファイルもKotlinらしい書き方になります。
基本の設定例は次の通りです。通常のKotlin/JVMプロジェクトで、JUnit 5、Kotlin標準のテストAPI、Mockito Kotlin、MockK、コルーチンテストを使えるようにしています。
plugins {
kotlin("jvm") version "2.0.21"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
testImplementation("org.junit.jupiter:junit-jupiter:5.10.3")
testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
testImplementation("io.mockk:mockk:1.13.12")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
}
tasks.test {
useJUnitPlatform()
}
useJUnitPlatform()を書いておくと、JUnit 5のテストをGradleから正しく実行できます。これがないと、テストコードを書いても実行対象として認識されないことがあります。
tasks.test { useJUnitPlatform() }も確認しましょう。Kotlin初心者がテスト実行でつまずきやすいポイントです。
テストを実行するコマンドは次の通りです。Windowsの場合はgradlew.bat test、MacやLinuxの場合は./gradlew testを使います。
./gradlew test
./gradlew test --tests "CalculatorTest"
3. JUnit 5でKotlinの関数をテストする基本コード
まずは一番基本になるJUnit 5の単体テストを見てみましょう。ここでは、商品価格と税率から税込み金額を計算するPriceCalculatorクラスを作り、その結果が正しいかをテストします。
class PriceCalculator {
fun taxIncluded(price: Int, taxRate: Double): Int {
return (price * (1 + taxRate)).toInt()
}
}
このクラスに対して、JUnit 5でテストを書くと次のようになります。assertEqualsは「期待する値」と「実際の値」が同じかを確認するための関数です。
import kotlin.test.Test
import kotlin.test.assertEquals
class PriceCalculatorTest {
private val calculator = PriceCalculator()
@Test
fun taxIncluded_returnsPriceWithTax() {
val actual = calculator.taxIncluded(price = 1000, taxRate = 0.10)
assertEquals(1100, actual)
}
}
このテストでは、1000円の商品に10%の税率をかけた結果が1100円になることを確認しています。テストが成功すれば、計算ロジックが少なくともこの条件では正しく動いていると判断できます。
PriceCalculatorTest > taxIncluded_returnsPriceWithTax PASSED
Kotlinの単体テストでは、まずこのように「入力」「実行」「検証」の流れを意識すると書きやすくなります。複雑なテストを書く前に、シンプルな関数を1つずつ確認する習慣をつけることが大切です。
4. ParameterizedTestで入力パターンを増やす方法
実務のKotlin開発では、1つの入力だけをテストしても不十分なことがあります。価格計算、文字列チェック、バリデーションなどは、複数のパターンをまとめて確認したい場面が多いです。そのようなときはJUnit 5の@ParameterizedTestを使います。
たとえば、割引後の価格を計算する関数を作ってみます。
class DiscountService {
fun applyDiscount(price: Int, discountRate: Double): Int {
return (price * (1 - discountRate)).toInt()
}
}
この関数に対して、複数の価格と割引率を一度にテストするコードは次の通りです。
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import kotlin.test.assertEquals
class DiscountServiceTest {
private val service = DiscountService()
@ParameterizedTest
@CsvSource(
"1000, 0.10, 900",
"2500, 0.20, 2000",
"800, 0.00, 800"
)
fun applyDiscount_returnsDiscountedPrice(
price: Int,
discountRate: Double,
expected: Int
) {
val actual = service.applyDiscount(price, discountRate)
assertEquals(expected, actual)
}
}
@CsvSourceを使うと、テストデータを表のように並べられます。価格や割引率の境界値を追加しやすくなるため、Kotlinでビジネスロジックをテストするときにとても便利です。
5. Mockito KotlinでRepositoryをモック化する実務例
Mockito Kotlinは、外部の部品を本物の代わりに用意するためのテストツールです。たとえば、ユーザー情報をDBから取得するUserRepositoryがある場合、本物のDBに接続しなくてもテストできるようになります。
まず、RepositoryとServiceの例を作ります。ServiceはRepositoryから名前を取得し、画面表示用のメッセージを作る役割です。
interface UserRepository {
fun findName(userId: Int): String?
}
class UserService(
private val repository: UserRepository
) {
fun greeting(userId: Int): String {
val name = repository.findName(userId) ?: return "ユーザーが見つかりません"
return "こんにちは、$name さん"
}
}
このUserServiceをMockito Kotlinでテストします。mock()でRepositoryの偽物を作り、wheneverで戻り値を指定します。
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import kotlin.test.Test
import kotlin.test.assertEquals
class UserServiceTest {
private val repository: UserRepository = mock()
private val service = UserService(repository)
@Test
fun greeting_returnsUserNameMessage() {
whenever(repository.findName(1001)).thenReturn("佐藤")
val actual = service.greeting(1001)
assertEquals("こんにちは、佐藤 さん", actual)
verify(repository).findName(1001)
}
}
verifyを使うと、RepositoryのfindNameが指定したIDで呼び出されたかも確認できます。単に戻り値だけを見るのではなく、依存先とのやり取りまで確認できるのがMockito Kotlinの便利な点です。
org.mockito.kotlinを使うと、Kotlinのnull安全に合った書き方になり、テストコードが読みやすくなります。
6. KotlinではMockKも選択肢に入れる理由
Kotlinのテストでは、Mockito KotlinだけでなくMockKもよく使われます。理由は、Kotlinのクラスが標準でfinalであること、object宣言やコルーチンなどKotlin特有の機能を扱う場面があることです。MockKはKotlin向けに作られているため、Kotlinらしいコードと相性が良いです。
たとえば、通知メッセージを送るクラスをモック化して、メソッドが呼び出されたかを確認してみます。
class NotificationClient {
fun send(message: String) {
println("送信: $message")
}
}
class NotificationService(
private val client: NotificationClient
) {
fun notifyLogin(name: String) {
client.send("$name さんがログインしました")
}
}
MockKを使ったテストコードは次の通りです。everyで動作を指定し、verifyで呼び出しを確認します。
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlin.test.Test
class NotificationServiceTest {
@Test
fun notifyLogin_sendsLoginMessage() {
val client = mockk<NotificationClient>(relaxed = true)
val service = NotificationService(client)
every { client.send(any()) } returns Unit
service.notifyLogin("田中")
verify {
client.send("田中 さんがログインしました")
}
}
}
relaxed = trueを指定すると、戻り値のない関数などに対して細かい設定を書かなくてもテストしやすくなります。ただし便利だからといって使いすぎると、意図しない呼び出しを見逃すこともあるため、重要な処理はverifyで確認しましょう。
- Mockito Kotlin:Java資産が多いプロジェクトや既存Mockito文化と相性がよい
- MockK:Kotlin特有のfinal class、object、coroutineを扱いやすい
- JUnit 5:どちらのモックツールとも組み合わせられるテスト実行基盤
7. コルーチン処理をrunTestでテストする方法
Kotlinでは非同期処理にコルーチンを使うことがあります。コルーチンとは、処理を一時停止したり再開したりしながら、効率よく非同期処理を書くための仕組みです。通信処理、DB処理、時間のかかる計算などでよく使われます。
コルーチンをテストするときは、kotlinx-coroutines-testのrunTestを使うと書きやすくなります。まず、非同期でプロフィール名を取得するクラスを用意します。
import kotlinx.coroutines.delay
class ProfileApi {
suspend fun fetchName(userId: Int): String {
delay(100)
return "User-$userId"
}
}
class ProfileService(
private val api: ProfileApi
) {
suspend fun displayName(userId: Int): String {
return "表示名: ${api.fetchName(userId)}"
}
}
このようなsuspend関数をテストする場合、通常の@Test関数の中でrunTestを使います。
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
class ProfileServiceTest {
@Test
fun displayName_returnsFormattedName() = runTest {
val service = ProfileService(ProfileApi())
val actual = service.displayName(42)
assertEquals("表示名: User-42", actual)
}
}
runTestを使うと、コルーチンのテストを安定して実行できます。KotlinでAndroidアプリやサーバーサイド処理を書く場合、コルーチンのテストは重要になるため、早めに覚えておきたい書き方です。
8. テストツールを使うときの失敗しやすいポイント
Kotlinのテストツールは便利ですが、書き方を間違えると保守しにくいテストになってしまいます。特に初心者は、実装の細かい手順を確認しすぎたり、何を検証しているのか分からないテスト名にしてしまうことがあります。
たとえば、次のようなテスト名だと内容が伝わりにくくなります。
@Test
fun test1() {
// 何を確認しているか分かりにくい
}
テスト名は、あとで読んだ人が「どんな条件で、何を期待しているのか」を理解できる名前にしましょう。
@Test
fun greeting_returnsNotFoundMessageWhenUserDoesNotExist() {
// 存在しないユーザーIDの場合の表示文言を確認する
}
また、MockitoやMockKで何でもモック化しすぎると、実際の動作とかけ離れたテストになることがあります。計算や文字列変換のような純粋なロジックはJUnitだけで確認し、外部APIやDBのように準備が重い部分だけモック化するとバランスがよくなります。
9. JUnit・Mockito・MockKを選ぶ基準
Kotlinのテストツールは、目的に合わせて選ぶと使いやすくなります。すべての場面でMockito Kotlinだけを使う必要はありませんし、すべてをMockKに寄せる必要もありません。まずはJUnit 5で関数の結果を確認し、外部の部品が必要になったらMockito KotlinやMockKを追加する考え方が自然です。
計算処理、文字列変換、バリデーション、例外発生など、入力と結果がはっきりしているテストに向いています。
Repository、APIクライアント、メール送信処理など、別クラスとのやり取りを確認したいときに便利です。
Kotlinらしいfinal class、object、suspend関数、コルーチンを扱うテストで候補に入れたいツールです。
10. 次に練習したいKotlin単体テストの作り方
この記事の内容を実際に身につけるには、小さなKotlinコードに対してテストを書く練習が効果的です。いきなり大きなアプリをテストしようとすると、どこから確認すればよいか分かりにくくなります。まずは、入力と出力がはっきりした関数から始めましょう。
- 料金計算や割引計算をJUnit 5で確認する
- 存在しないユーザーをRepositoryモックで再現する
- 正常系だけでなく、nullや例外のパターンもテストする
- コルーチン処理は
runTestで安定して確認する
テストを書けるようになると、Kotlinのコードを安心して変更できるようになります。リファクタリング、機能追加、ライブラリ更新を行うときにも、テストがあることで「壊れていないか」をすぐに確認できます。
生徒
「JUnit、Mockito、MockKの違いが少し分かってきました。最初はどれから練習すればいいですか?」
先生
「まずはJUnit 5で小さな関数をテストしましょう。次にRepositoryをモック化して、Serviceの動きを確認します。Kotlinのfinal classやコルーチンで困ったらMockKも試すとよいですよ。」
生徒
「テストを書くと、コードを直すときも安心できそうですね。」
先生
「その通りです。Kotlinのテストツールは、学習だけでなく実務の保守性や品質向上にも直結します。」
Kotlinを基礎からしっかり学びたい人や、 Java経験を活かしてモダンな言語にステップアップしたい人には、 定番の入門書がこちらです。
基礎からわかるKotlinをAmazonで見る※ Amazon広告リンク
まとめ
Kotlinのテストツール活用例では、テストツール活用例をKotlinで扱うときの考え方を確認しました。Kotlinテストは、書き方だけを覚えるよりも、IntelliJ IDEAやGradleで小さく動かしながら「どこで値が変わるのか」「失敗したときに何が起きるのか」を見たほうが理解しやすくなります。
実装前のメモ
- テストツール活用例で注目する場所として、テスト名、準備する値、実行する処理、期待する結果、失敗時のメッセージを説明できる
- 正常系に加えて、空文字、null、例外、境界値のテストを1つずつ増やす
- IntelliJ IDEAのエラー、警告、コンソール出力を読み、原因を1つ言葉にできる
- Kotlin、Gradle、Android、サーバーサイド開発の中で、この記事の知識を使う場面を想像できる
復習するときは、次のような短いコードを自分の環境で動かしてみましょう。記事のテーマに合わせて値や条件を変えると、Kotlinのnull安全、data class、例外処理、非同期処理の見え方が少しずつ整理できます。
import kotlin.test.Test
import kotlin.test.assertEquals
class PriceTest {
@Test
fun totalPrice() {
assertEquals(300, 100 * 3)
}
}
生徒
「テストツール活用例は、どこを変えて試せばいいか分かると復習しやすいですね。」
先生
「はい。まずは小さく動かし、次に失敗するケースを1つ足してみましょう。Kotlinは型やnull安全がヒントを出してくれるので、結果を見ながら直す練習がそのまま実務力につながります。」
【未経験OK】Kotlinで始めるプログラミング入門|ゼロから「動く喜び」を体験する60分
「プログラミングを始めたい」を形にする。最新言語Kotlinで楽しむ、ものづくりの第一歩。
本講座は、プログラミング経験が全くない方のためのエントリー講座です。「コードを書くってどういうこと?」という基本から、世界中で使われている最新言語Kotlin(コトリン)を使って、実際にプログラムを動かすまでを体験します。難しい理屈よりも、まずは「自分の手で動かす楽しさ」を最短距離で実感していただきます。
具体的な体験内容と環境
【つくるもの】
簡単な言葉を入力すると自動で返答してくれる「対話型ミニプログラム」や、計算を自動化する「便利ツール」をゼロから作成します。黒い画面に自分の書いた文字が表示される瞬間は、最高の感動体験です。
【開発環境】
プロのエンジニアが実際に使っている開発ツールIntelliJ IDEA(インテリジェイ)をインストールします。ボタン一つで日本語化し、初心者でも迷わず操作できる「魔法の設定」を一緒に行います。
この60分で得られる3つの体験
プロと同じ道具を揃えることで、明日から一人でもプログラミングを続けられる環境が整います。
「変数」や「型」といった難しい言葉も、身近な例え話で解説。モヤモヤをゼロにします。
Kotlinは英語に近くて読みやすいのが特徴。自分でコードを読んで、間違いを見つけるコツも伝授します。
※本講座は、パソコン操作が不安な方でも安心して受講いただける完全マンツーマンです。あなたのペースに合わせて、一つずつ丁寧に進めていきます。
Kotlinで始めるプログラミング入門|ゼロから「動く喜び」を体験