Skip to content

Commit

Permalink
Finish transition to kotlin.test of retrofit and fx-coroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
serras committed Nov 8, 2023
1 parent 0c39851 commit 0a21aa9
Show file tree
Hide file tree
Showing 18 changed files with 294 additions and 215 deletions.
2 changes: 0 additions & 2 deletions arrow-libs/core/arrow-core-retrofit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ dependencies {
testImplementation(projects.arrowCore)
testImplementation(libs.kotlin.test)
testImplementation(libs.coroutines.test)
testImplementation(libs.kotest.frameworkEngine)
testImplementation(libs.kotest.assertionsCore)
testImplementation(libs.kotest.property)
testCompileOnly(libs.kotlin.reflect)
testRuntimeOnly(libs.kotest.runnerJUnit5)
testImplementation(libs.squareup.okhttpMockWebServer)
testImplementation(libs.squareup.retrofitConverterGson)
testImplementation(libs.squareup.retrofitConverterMoshi)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import arrow.core.right
import arrow.retrofit.adapter.either.EitherCallAdapterFactory
import arrow.retrofit.adapter.mock.ResponseMock
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.spec.style.stringSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
Expand All @@ -24,21 +22,17 @@ import retrofit2.converter.moshi.MoshiConverterFactory
import java.net.SocketException
import java.net.SocketTimeoutException
import java.util.concurrent.TimeUnit
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test

@ExperimentalSerializationApi
class NetworkEitherCallAdapterTestSuite : StringSpec({
include(networkEitherCallAdapterTests(GsonConverterFactory.create()))
include(networkEitherCallAdapterTests(MoshiConverterFactory.create()))
include(networkEitherCallAdapterTests(Json.asConverterFactory("application/json".toMediaType())))
})
abstract class NetworkEitherCallAdapterTest(
private val jsonConverterFactory: Converter.Factory,
) {
private var server: MockWebServer? = null
private var service: CallErrorTestClient? = null

private fun networkEitherCallAdapterTests(
jsonConverterFactory: Converter.Factory,
) = stringSpec {
var server: MockWebServer? = null
var service: CallErrorTestClient? = null

beforeAny {
open fun initialize() {
server = MockWebServer()
server!!.start()
val client = OkHttpClient.Builder()
Expand All @@ -52,17 +46,20 @@ private fun networkEitherCallAdapterTests(
.build()
.create(CallErrorTestClient::class.java)
}
afterAny { server!!.shutdown() }

"should return ResponseMock for 200 with valid JSON" {
open fun shutdown() {
server!!.shutdown()
}

open fun shouldReturn200ForValidJson() = runTest {
server!!.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))

val body = service!!.getEither()

body shouldBe ResponseMock("Arrow rocks").right()
}

"should return HttpError for 400" {
open fun shouldReturnHttpErrorFor404() = runTest {
server!!.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400))

val body = service!!.getEither()
Expand All @@ -74,7 +71,7 @@ private fun networkEitherCallAdapterTests(
).left()
}

"should return CallError for 200 with invalid JSON" {
open fun shouldReturnCallErrorFor200InvalidJson() = runTest {
server!!.enqueue(MockResponse().setBody("""not a valid JSON"""))

val body = service!!.getEither()
Expand All @@ -83,7 +80,7 @@ private fun networkEitherCallAdapterTests(
.value.shouldBeInstanceOf<CallError>()
}

"should return HttpError for 400 and invalid JSON" {
open fun shouldReturnHttpErrorFor404InvalidJson() = runTest {
server!!.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400))

val body = service!!.getEither()
Expand All @@ -95,7 +92,7 @@ private fun networkEitherCallAdapterTests(
).left()
}

"should return IOError when server disconnects" {
open fun shouldReturnIOErrorDisconnect() = runTest {
server!!.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AT_START })

val body = service!!.getEither()
Expand All @@ -105,7 +102,7 @@ private fun networkEitherCallAdapterTests(
.cause.shouldBeInstanceOf<SocketException>()
}

"should return IOError when no response" {
open fun shouldReturnIOErrorNoResponse() = runTest {
server!!.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.NO_RESPONSE })

val body = service!!.getEither()
Expand All @@ -115,23 +112,23 @@ private fun networkEitherCallAdapterTests(
.cause.shouldBeInstanceOf<SocketTimeoutException>()
}

"should return Unit when service method returns Unit and null body received" {
open fun shouldReturnUnitForNullBody() = runTest {
server!!.enqueue(MockResponse().setResponseCode(204))

val body = service!!.postSomething("Sample string")

body shouldBe Unit.right()
}

"should return Unit when service method returns Unit and JSON body received" {
open fun shouldReturnUnitForUnitBody() = runTest {
server!!.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))

val body = service!!.postSomething("Sample string")

body shouldBe Unit.right()
}

"should return CallError when service method returns type other than Unit but null body received" {
open fun shouldReturnCallErrorWithUnitForNonNullBody() = runTest {
server!!.enqueue(MockResponse())

val body = service!!.getEither()
Expand All @@ -140,3 +137,87 @@ private fun networkEitherCallAdapterTests(
.value.shouldBeInstanceOf<CallError>()
}
}

class NetworkEitherCallAdapterTestGson : NetworkEitherCallAdapterTest(GsonConverterFactory.create()) {
@BeforeTest override fun initialize() {
super.initialize()
}

@AfterTest override fun shutdown() {
super.shutdown()
}

@Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson()

@Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404()

@Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson()

@Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson()

@Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect()

@Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse()

@Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody()

@Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody()

@Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody()
}

class NetworkEitherCallAdapterTestMoshi : NetworkEitherCallAdapterTest(MoshiConverterFactory.create()) {
@BeforeTest override fun initialize() {
super.initialize()
}

@AfterTest override fun shutdown() {
super.shutdown()
}

@Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson()

@Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404()

@Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson()

@Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson()

@Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect()

@Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse()

@Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody()

@Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody()

@Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody()
}

class NetworkEitherCallAdapterTestKotlinxSerialization : NetworkEitherCallAdapterTest(Json.asConverterFactory("application/json".toMediaType())) {
@BeforeTest override fun initialize() {
super.initialize()
}

@AfterTest override fun shutdown() {
super.shutdown()
}

@Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson()

@Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404()

@Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson()

@Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson()

@Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect()

@Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse()

@Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody()

@Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody()

@Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody()
}
3 changes: 0 additions & 3 deletions arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ spotless {
}
}

apply(plugin = "io.kotest.multiplatform")

kotlin {
sourceSets {
commonMain {
Expand All @@ -31,7 +29,6 @@ kotlin {
implementation(projects.arrowCore)
implementation(libs.kotlin.test)
implementation(libs.coroutines.test)
implementation(libs.kotest.frameworkEngine)
implementation(libs.kotest.assertionsCore)
implementation(libs.kotest.property)
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import arrow.core.identity
import arrow.core.prependTo
import arrow.fx.coroutines.ExitCase.Companion.ExitCase
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
Expand Down Expand Up @@ -466,7 +465,6 @@ public fun <A> Resource<A>.asFlow(): Flow<A> =
* instead the caller is responsible for correctly invoking the `release` handler at the appropriate time.
* This API is useful for building inter-op APIs between [Resource] and non-suspending code, such as Java libraries.
*/
@DelicateCoroutinesApi
public suspend fun <A> Resource<A>.allocated(): Pair<A, suspend (ExitCase) -> Unit> {
val effect = ResourceScopeImpl()
val allocated: A = invoke(effect)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ import kotlinx.coroutines.test.currentTime
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.withTimeoutOrNull
import kotlin.test.Test
import kotlin.time.ExperimentalTime

@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
@ExperimentalTime
class FlowTest {

@Test
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.AtomicInt
import arrow.atomic.update
import arrow.atomic.value
import arrow.core.Either
import arrow.fx.coroutines.ExitCase
import arrow.fx.coroutines.awaitExitCase
import arrow.fx.coroutines.guaranteeCase
import arrow.fx.coroutines.leftException
import arrow.fx.coroutines.parZip
import arrow.fx.coroutines.throwable
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeTypeOf
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package arrow.fx.coroutines.parZip
package arrow.fx.coroutines

import arrow.atomic.Atomic
import arrow.atomic.update
Expand Down
Loading

0 comments on commit 0a21aa9

Please sign in to comment.