OkHttpの実装リポジトリOkHttpHtmlRepositoryImplの単体(JVM上で行う)テストを行います。
※単にサイトからHTMLを取得するだけですので、単体テストの必要性はほぼありません。
単体テストには下記のライブラリモジュールを使用します。
バージョンカタログファイルにOkHttpのバージョン定義を追記します。
[versions]
:
# Test
kotlinx-coroutines-test = "1.10.2" # https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-test
mockk = "1.14.6" # https://mvnrepository.com/artifact/io.mockk/mockk
[libraries]
:
# Test
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines-test" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
:
追記後、『Sync Now』で内容をプロジェクトに反映させます。
OkHttpのテストに必要なライブラリを:core:dataモジュールのbuild.gradle.ktsに追記します。
plugins {
:
id("de.mannodermaus.android-junit5")
}
:
dependencies {
:
// ローカル単体テスト (src/test)
testImplementation(libs.bundles.junit5)
testRuntimeOnly(libs.junit5.engine)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockk)
testImplementation(libs.okhttp.mockwebserver)
}
追記後、『同期アイコン』で内容をプロジェクトに反映させます。
:core:dataモジュールのTestにテスト用クラスを作成します。
ファイル名をOkHttpHtmlRepositoryImplTestにしています。
package jp.co.example.android01.core.data.repository
import kotlinx.coroutines.test.runTest
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
import jp.co.example.android01.core.data.repository.OkHttpHtmlRepositoryImpl
class OkHttpHtmlRepositoryImplTest {
private lateinit var mockWebServer: MockWebServer
private lateinit var repository: OkHttpHtmlRepositoryImpl
@BeforeEach
fun setUp() {
mockWebServer = MockWebServer()
mockWebServer.start()
repository = OkHttpHtmlRepositoryImpl()
}
@AfterEach
fun tearDown() {
mockWebServer.shutdown()
}
// 成功時_HTMLコンテンツを返す
@Test
fun getHtmlContent_Test200() = runTest {
// Given
val expectedHtml = """
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is a test page.</p>
</body>
</html>
""".trimIndent()
mockWebServer.enqueue(
MockResponse()
.setResponseCode(200)
.setBody(expectedHtml)
.addHeader("Content-Type", "text/html; charset=utf-8")
)
// When
val url = mockWebServer.url("/test").toString()
val result = repository.getHtmlContent(url)
// Then
println("=== Test200 Result ===")
println("Success: ${result.isSuccess}")
println("Content: ${result.getOrNull()}")
println("Expected: $expectedHtml")
println("=====================")
assertTrue(result.isSuccess)
assertEquals(expectedHtml, result.getOrNull())
}
// 404エラー時_失敗を返す
@Test
fun getHtmlContent_Test404() = runTest {
// Given
mockWebServer.enqueue(
MockResponse()
.setResponseCode(404)
.setBody("Not Found")
)
// When
val url = mockWebServer.url("/notfound").toString()
val result = repository.getHtmlContent(url)
// Then
println("=== Test404 Result ===")
println("Success: ${result.isSuccess}")
println("Failure: ${result.isFailure}")
println("Exception: ${result.exceptionOrNull()?.message}")
println("=====================")
assertTrue(result.isFailure)
assertTrue(result.exceptionOrNull()?.message?.contains("HTTP Error: 404") == true)
}
// 500エラー時_失敗を返す
@Test
fun getHtmlContent_Test500() = runTest {
// Given
mockWebServer.enqueue(
MockResponse()
.setResponseCode(500)
.setBody("Internal Server Error")
)
// When
val url = mockWebServer.url("/error").toString()
val result = repository.getHtmlContent(url)
// Then
assertTrue(result.isFailure)
assertTrue(result.exceptionOrNull()?.message?.contains("HTTP Error: 500") == true)
}
// 空のレスポンス時 空文字列を返す
@Test
fun getHtmlContent_TestEmpty() = runTest {
// Given
mockWebServer.enqueue(
MockResponse()
.setResponseCode(200)
.setBody("")
)
// When
val url = mockWebServer.url("/empty").toString()
val result = repository.getHtmlContent(url)
// Then
assertTrue(result.isSuccess)
assertEquals("", result.getOrNull())
}
// 大きなHTMLコンテンツ時_正常に処理される
@Test
fun getHtmlContent_TestLarge() = runTest {
// Given
val largeHtml = buildString {
append("<!DOCTYPE html><html><head><title>Large Page</title></head><body>")
repeat(1000) { i ->
append("<p>This is paragraph number $i with some content.</p>")
}
append("</body></html>")
}
mockWebServer.enqueue(
MockResponse()
.setResponseCode(200)
.setBody(largeHtml)
.addHeader("Content-Type", "text/html; charset=utf-8")
)
// When
val url = mockWebServer.url("/large").toString()
val result = repository.getHtmlContent(url)
// Then
assertTrue(result.isSuccess)
assertEquals(largeHtml, result.getOrNull())
assertTrue((result.getOrNull()?.length ?: 0) > 10000)
}
}
テストの実行は、Android Studioのターミナルで行います。
./gradlew :core:data:testDebugUnitTest --info ./gradlew :core:data:testDebugUnitTest --info --tests "OkHttpHtmlRepositoryImplTest" ./gradlew :core:data:testDebugUnitTest --info --tests "OkHttpHtmlRepositoryImplTest.getHtmlContent_Test200"
実行結果は、/core/data/build/reports/tests/testDebugUnitTest/内に作成されています。
index.htmlを開きます。
index.htmlを開くと、ブラウザのアイコンが表示されます。
クリックしてブラウザを開きます。
サマリーブラウザでサマリーが表示されます。
テストしたパッケージをクリックします。
クラスパッケージ内のテスト用クラスが表示されます。
テストしたクラスをクリックします。
標準出力テスト関数内でprintlnした内容が、Standard outputタブ内に表示されます。