0Pricing
Android Academy · レッスン

JUnitによるユニットテスト

JUnit 4で高速かつ信頼性の高いユニットテストを記述します。@Test、@Before、@After、アサーションを使い、InstantTaskExecutorRuleでLiveDataを、runTestでコルーチンをテストします。

「JUnitによるユニットテスト」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全4レッスンが含まれています。

なぜテストを書くのですか?

テストはぜいたく品ではなく、コードを守る安全網です:

  • ユーザーが見つける前にバグを発見できます
  • 安心してリファクタリングできます(テストが通れば、動作が壊れていないと確認できます)
  • 意図した動作を文書化できます
  • 機能追加時のデグレードを防げます

十分にテストされたコードは、設計も優れている傾向があります。テストが難しい場合は、設計の結合度が高すぎる可能性があります。

Androidのテストの種類

テストには2つのカテゴリがあります:

  • Unit tests(test/フォルダー) — JVM上で実行するため、デバイスは不要です。高速で、純粋なKotlin/Javaのロジックをテストします。
  • Instrumented tests(androidTest/フォルダー) — デバイスまたはエミュレーター上で実行します。時間はかかりますが、Android固有のコード(Room DB、UI)をテストできます。

ビジネスロジックには、できるだけユニットテストを使用してください。Android APIとのやり取りが必要な場合にのみ、インストルメンテーションテストを使用します。

JUnit 4のセットアップ

JUnit 4はAndroidプロジェクトにデフォルトで含まれています。app/build.gradleに次を追加します:

// app/build.gradle:
dependencies {
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
    testImplementation 'androidx.arch.core:core-testing:2.2.0'  // for LiveData
}

最初のJUnitテスト

src/test/java/にクラスを作成し、テストメソッドに@Testを付けます:

import org.junit.Test
import org.junit.Assert.*

class CalculatorTest {

    private val calc = Calculator()

    @Test
    fun `addition returns correct sum`() {
        val result = calc.add(2, 3)
        assertEquals(5, result)
    }

    @Test
    fun `division by zero throws exception`() {
        assertThrows(ArithmeticException::class.java) {
            calc.divide(10, 0)
        }
    }
}

@Beforeと@After

ライフサイクルアノテーションを使用して、各テストの前後に状態をセットアップおよび破棄します:

class UserRepositoryTest {

    private lateinit var repo: UserRepository
    private lateinit var fakeDao: FakeUserDao

    @Before
    fun setUp() {
        fakeDao = FakeUserDao()          // fresh instance before each test
        repo = UserRepository(fakeDao)
    }

    @After
    fun tearDown() {
        fakeDao.clear()                  // clean up after each test
    }

    @Test
    fun `getUsers returns all users`() {
        fakeDao.insert(User(1, "Alice"))
        fakeDao.insert(User(2, "Bob"))
        assertEquals(2, repo.getUsers().size)
    }
}

よく使うアサーション

JUnitにはAssert.*のアサーションメソッドが用意されています:

// Equality:
assertEquals(expected, actual)
assertNotEquals(unexpected, actual)

// Null:
assertNull(value)
assertNotNull(value)

// Boolean:
assertTrue(condition)
assertFalse(condition)

// Same object reference:
assertSame(expected, actual)

// Custom message on failure:
assertEquals("User ID should be 1", 1, user.id)

// Exception:
assertThrows(IllegalArgumentException::class.java) {
    User(id = -1, name = "")
}

ViewModelのテスト

LiveDataをテストするには、LiveDataの投稿を同期的に実行するInstantTaskExecutorRuleを追加します:

class UserViewModelTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val fakeRepo = FakeUserRepository()
    private lateinit var viewModel: UserViewModel

    @Before
    fun setUp() {
        viewModel = UserViewModel(fakeRepo)
    }

    @Test
    fun `users are loaded on init`() {
        fakeRepo.usersToReturn = listOf(User(1, "Alice"), User(2, "Bob"))
        viewModel.loadUsers()

        val result = viewModel.users.value
        assertNotNull(result)
        assertEquals(2, result?.size)
    }
}

コルーチンのテスト

TestCoroutineDispatcher/StandardTestDispatcherを使用して、テスト中のコルーチンの実行を制御します:

class SyncWorkerTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val testDispatcher = StandardTestDispatcher()

    @Before
    fun setUp() {
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `sync completes successfully`() = runTest {
        val repo = FakeRepository()
        val worker = SyncUseCase(repo, testDispatcher)
        val result = worker.run()
        assertTrue(result.isSuccess)
    }
}

FakeとMock

テストで実際の依存関係を置き換える方法は2つあります:

  • Fake — テスト用に作られた、動作する実装です(例:実際のデータベースの代わりにメモリ上のリストを使用する)。作成しやすく読みやすいうえ、ライブラリも必要ありません。
  • Mock — 呼び出しを記録し、やり取りを検証できる自動生成のスタブです(Mockito、MockK)。より強力ですが、使いすぎると壊れやすくなります。

単純なケースではFakeを優先し、メソッド呼び出しの検証が必要な場合はMockを使用してください。

Fakeの作成

Fakeは実際のクラスと同じインターフェースを実装しますが、メモリ上にデータを保存します:

interface UserDao {
    fun getAll(): List<User>
    fun insert(user: User)
}

class FakeUserDao : UserDao {
    private val storage = mutableListOf<User>()

    override fun getAll(): List<User> = storage.toList()
    override fun insert(user: User) { storage.add(user) }

    fun clear() { storage.clear() }
}

テスト名の規約

適切なテスト名は、何をテストしているかと期待される結果を表します。Kotlinでは、読みやすい説明にするため、バッククォートで囲んだ関数名を使用します:

  • `getUsers returns empty list when no users exist`
  • `login throws exception when password is blank`
  • `add returns correct sum for negative numbers`

パターン:`subject does X when Y`

確認問題

JUnitのテストクラスにおける@Beforeの役割は何ですか?

まとめ:JUnitによるユニットテスト

信頼できるアプリは、テストされたアプリです:

  • ユニットテストはsrc/test/に配置し、JVM上で高速に実行します
  • @Testを付け、assertEquals、assertTrue、assertThrowsを使用します
  • セットアップと破棄には@Before/@Afterを使用します
  • LiveDataを同期的にテストするにはInstantTaskExecutorRuleを使用します
  • コルーチンのテストにはrunTest + StandardTestDispatcherを使用します
  • 単純な置き換えにはMockよりFakeを優先します

次は、やり取りを検証するためのMockitoによるモックです。

よくある質問

「JUnitによるユニットテスト」レッスンは無料ですか?

はい。「JUnitによるユニットテスト」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全4レッスンが含まれています。

「JUnitによるユニットテスト」で何を学びますか?

JUnit 4で高速かつ信頼性の高いユニットテストを記述します。@Test、@Before、@After、アサーションを使い、InstantTaskExecutorRuleでLiveDataを、runTestでコルーチンをテストします。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Android Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「JUnitによるユニットテスト」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAndroid Academyレッスンでコードを書いて実行できますか?

はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. JUnitによるユニットテスト
  2. Mockitoによるモック
  3. EspressoによるUIテスト
  4. デバッグとプロファイリング
← Android Academyに戻る