From 22d19b4c04c43ff1be328b31d58021c539bc34c1 Mon Sep 17 00:00:00 2001 From: Kirill Kamakin Date: Sat, 13 Nov 2021 17:49:35 +0300 Subject: [PATCH] Extract generic test code --- .../data/auth/impl/AuthDataSourceImplTest.kt | 64 ++++--------------- .../mealie/data/auth/impl/AuthImplTestData.kt | 35 ++++++++++ .../data/auth/impl/AuthStorageImplTest.kt | 10 +-- .../{BaseTest.kt => HiltRobolectricTest.kt} | 2 +- .../mealie/data/auth/impl/MockServerTest.kt | 23 +++++++ 5 files changed, 73 insertions(+), 61 deletions(-) create mode 100644 app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthImplTestData.kt rename app/src/test/java/gq/kirmanak/mealie/data/auth/impl/{BaseTest.kt => HiltRobolectricTest.kt} (93%) create mode 100644 app/src/test/java/gq/kirmanak/mealie/data/auth/impl/MockServerTest.kt diff --git a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthDataSourceImplTest.kt b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthDataSourceImplTest.kt index 8dd0fc7..73d6f91 100644 --- a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthDataSourceImplTest.kt +++ b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthDataSourceImplTest.kt @@ -2,57 +2,42 @@ package gq.kirmanak.mealie.data.auth.impl import com.google.common.truth.Truth.assertThat import dagger.hilt.android.testing.HiltAndroidTest +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.TEST_PASSWORD +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.TEST_TOKEN +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.TEST_USERNAME +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.body +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.enqueueSuccessfulAuthResponse +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.enqueueUnsuccessfulAuthResponse import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import kotlinx.serialization.ExperimentalSerializationApi -import okhttp3.mockwebserver.MockResponse -import okhttp3.mockwebserver.MockWebServer -import okhttp3.mockwebserver.RecordedRequest -import org.junit.After -import org.junit.Before import org.junit.Test import retrofit2.HttpException -import java.nio.charset.Charset import javax.inject.Inject @ExperimentalSerializationApi @ExperimentalCoroutinesApi @HiltAndroidTest -class AuthDataSourceImplTest : BaseTest() { +class AuthDataSourceImplTest : MockServerTest() { @Inject lateinit var subject: AuthDataSourceImpl - private lateinit var mockServer: MockWebServer - private lateinit var serverUrl: String - - @Before - fun startMockServer() { - mockServer = MockWebServer().apply { - start() - } - serverUrl = mockServer.url("/").toString() - } - - @After - fun stopMockServer() { - mockServer.shutdown() - } @Test fun `when authentication is successful then token is correct`() = runBlocking { - enqueueSuccessfulResponse() + mockServer.enqueueSuccessfulAuthResponse() val token = subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl) assertThat(token).isEqualTo(TEST_TOKEN) } @Test(expected = HttpException::class) fun `when authentication isn't successful then throws`(): Unit = runBlocking { - enqueueUnsuccessfulResponse() + mockServer.enqueueUnsuccessfulAuthResponse() subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl) } @Test fun `when authentication is requested then body is correct`() = runBlocking { - enqueueSuccessfulResponse() + mockServer.enqueueSuccessfulAuthResponse() subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl) val body = mockServer.takeRequest().body() assertThat(body).isEqualTo("username=$TEST_USERNAME&password=$TEST_PASSWORD") @@ -60,37 +45,10 @@ class AuthDataSourceImplTest : BaseTest() { @Test fun `when authentication is requested then path is correct`() = runBlocking { - enqueueSuccessfulResponse() + mockServer.enqueueSuccessfulAuthResponse() subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl) val path = mockServer.takeRequest().path assertThat(path).isEqualTo("/api/auth/token") } - private fun RecordedRequest.body() = body.readString(Charset.defaultCharset()) - - private fun enqueueUnsuccessfulResponse() { - val response = MockResponse() - .setBody(UNSUCCESSFUL_AUTH_RESPONSE) - .setHeader("Content-Type", "application/json") - .setResponseCode(401) - mockServer.enqueue(response) - } - - private fun enqueueSuccessfulResponse() { - val response = MockResponse() - .setBody(SUCCESSFUL_AUTH_RESPONSE) - .setHeader("Content-Type", "application/json") - .setResponseCode(200) - mockServer.enqueue(response) - } - - companion object { - private const val TEST_USERNAME = "TEST_USERNAME" - private const val TEST_PASSWORD = "TEST_PASSWORD" - private const val TEST_TOKEN = "TEST_TOKEN" - private const val SUCCESSFUL_AUTH_RESPONSE = - "{\"access_token\":\"$TEST_TOKEN\",\"token_type\":\"TEST_TOKEN_TYPE\"}" - private const val UNSUCCESSFUL_AUTH_RESPONSE = - "{\"detail\":\"Unauthorized\"}" - } } \ No newline at end of file diff --git a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthImplTestData.kt b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthImplTestData.kt new file mode 100644 index 0000000..00077aa --- /dev/null +++ b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthImplTestData.kt @@ -0,0 +1,35 @@ +package gq.kirmanak.mealie.data.auth.impl + +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest +import java.nio.charset.Charset + +object AuthImplTestData { + const val TEST_USERNAME = "TEST_USERNAME" + const val TEST_PASSWORD = "TEST_PASSWORD" + const val TEST_TOKEN = "TEST_TOKEN" + const val SUCCESSFUL_AUTH_RESPONSE = + "{\"access_token\":\"$TEST_TOKEN\",\"token_type\":\"TEST_TOKEN_TYPE\"}" + const val UNSUCCESSFUL_AUTH_RESPONSE = + "{\"detail\":\"Unauthorized\"}" + const val TEST_URL = "TEST_URL" + + fun RecordedRequest.body() = body.readString(Charset.defaultCharset()) + + fun MockWebServer.enqueueUnsuccessfulAuthResponse() { + val response = MockResponse() + .setBody(UNSUCCESSFUL_AUTH_RESPONSE) + .setHeader("Content-Type", "application/json") + .setResponseCode(401) + enqueue(response) + } + + fun MockWebServer.enqueueSuccessfulAuthResponse() { + val response = MockResponse() + .setBody(SUCCESSFUL_AUTH_RESPONSE) + .setHeader("Content-Type", "application/json") + .setResponseCode(200) + enqueue(response) + } +} \ No newline at end of file diff --git a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthStorageImplTest.kt b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthStorageImplTest.kt index 5732160..92ed144 100644 --- a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthStorageImplTest.kt +++ b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/AuthStorageImplTest.kt @@ -2,12 +2,14 @@ package gq.kirmanak.mealie.data.auth.impl import com.google.common.truth.Truth.assertThat import dagger.hilt.android.testing.HiltAndroidTest +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.TEST_TOKEN +import gq.kirmanak.mealie.data.auth.impl.AuthImplTestData.TEST_URL import kotlinx.coroutines.runBlocking import org.junit.Test import javax.inject.Inject @HiltAndroidTest -class AuthStorageImplTest : BaseTest() { +class AuthStorageImplTest : HiltRobolectricTest() { @Inject lateinit var subject: AuthStorageImpl @@ -37,10 +39,4 @@ class AuthStorageImplTest : BaseTest() { fun `when reading url without storing data then returns null`() = runBlocking { assertThat(subject.getBaseUrl()).isNull() } - - companion object { - private const val TEST_TOKEN = "TEST_TOKEN" - private const val TEST_URL = "TEST_URL" - } - } \ No newline at end of file diff --git a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/BaseTest.kt b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/HiltRobolectricTest.kt similarity index 93% rename from app/src/test/java/gq/kirmanak/mealie/data/auth/impl/BaseTest.kt rename to app/src/test/java/gq/kirmanak/mealie/data/auth/impl/HiltRobolectricTest.kt index e4767c3..0074c9c 100644 --- a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/BaseTest.kt +++ b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/HiltRobolectricTest.kt @@ -10,7 +10,7 @@ import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) @Config(application = HiltTestApplication::class) -abstract class BaseTest { +abstract class HiltRobolectricTest { @get:Rule var hiltRule = HiltAndroidRule(this) diff --git a/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/MockServerTest.kt b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/MockServerTest.kt new file mode 100644 index 0000000..0b3b1df --- /dev/null +++ b/app/src/test/java/gq/kirmanak/mealie/data/auth/impl/MockServerTest.kt @@ -0,0 +1,23 @@ +package gq.kirmanak.mealie.data.auth.impl + +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Before + +abstract class MockServerTest : HiltRobolectricTest() { + lateinit var mockServer: MockWebServer + lateinit var serverUrl: String + + @Before + fun startMockServer() { + mockServer = MockWebServer().apply { + start() + } + serverUrl = mockServer.url("/").toString() + } + + @After + fun stopMockServer() { + mockServer.shutdown() + } +} \ No newline at end of file