Skip to content

Commit

Permalink
Refactor REST API tests to use consistent async syntax
Browse files Browse the repository at this point in the history
Updated test syntax to use `in` for better readability and migrated to fully asynchronous assertions where applicable. Removed redundant `.futureValue` statements, ensuring non-blocking behavior across test methods.
  • Loading branch information
halotukozak committed Dec 23, 2024
1 parent 737fce1 commit 9a35f65
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 35 deletions.
21 changes: 13 additions & 8 deletions rest/.jvm/src/test/scala/io/udash/rest/SttpRestCallTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,27 @@ trait SttpClientRestTest extends ServletBasedRestApiTest {
}

class SttpRestCallTest extends SttpClientRestTest with RestApiTestScenarios {
test("too large binary request") {
val future = proxy.binaryEcho(Array.fill[Byte](maxPayloadSize + 1)(5))
val exception = future.failed.futureValue
assert(exception == HttpErrorException.plain(413, "Payload is larger than maximum 1048576 bytes (1048577)"))
"too large binary request" in {
proxy.binaryEcho(Array.fill[Byte](maxPayloadSize + 1)(5))
.failed
.map { exception =>
assert(exception == HttpErrorException.plain(413, "Payload is larger than maximum 1048576 bytes (1048577)"))
}
}
}

class ServletTimeoutTest extends SttpClientRestTest {
override def serverTimeout: FiniteDuration = 500.millis

test("rest method timeout") {
val exception = proxy.neverGet.failed.futureValue
assert(exception == HttpErrorException.plain(500, "server operation timed out after 500 milliseconds"))
"rest method timeout" in {
proxy.neverGet
.failed
.map { exception =>
assert(exception == HttpErrorException.plain(500, "server operation timed out after 500 milliseconds"))
}
}

test("subsequent requests with timeout") {
"subsequent requests with timeout" in {
assertThrows[HttpErrorException](Await.result(proxy.wait(600), Duration.Inf))
assertThrows[HttpErrorException](Await.result(proxy.wait(600), Duration.Inf))
assertThrows[HttpErrorException](Await.result(proxy.wait(600), Duration.Inf))
Expand Down
51 changes: 24 additions & 27 deletions rest/src/test/scala/io/udash/rest/RestApiTest.scala
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package io.udash
package rest

import cats.implicits.catsSyntaxTuple2Semigroupal
import com.avsystem.commons.*
import com.avsystem.commons.misc.ScalaDurationExtensions.durationIntOps
import io.udash.rest.raw.RawRest
import io.udash.rest.raw.RawRest.HandleRequest
import io.udash.testing.AsyncUdashSharedTest
import monix.eval.Task
import monix.execution.Scheduler
import org.scalactic.source.Position
import org.scalatest.BeforeAndAfterEach
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.time.{Millis, Seconds, Span}
import org.scalatest.{Assertion, BeforeAndAfterEach}

import scala.concurrent.duration.FiniteDuration

abstract class RestApiTest extends AnyFunSuite with ScalaFutures with BeforeAndAfterEach {
abstract class RestApiTest extends AsyncUdashSharedTest with BeforeAndAfterEach {
implicit def scheduler: Scheduler = Scheduler.global

protected final val MaxConnections: Int = 1 // to timeout quickly
Expand All @@ -38,11 +38,10 @@ abstract class RestApiTest extends AnyFunSuite with ScalaFutures with BeforeAndA
lazy val proxy: RestTestApi =
RawRest.fromHandleRequest[RestTestApi](clientHandle)

def testCall[T](call: RestTestApi => Future[T])(implicit pos: Position): Unit =
assert(
call(proxy).wrapToTry.futureValue.map(mkDeep) ==
call(impl).catchFailures.wrapToTry.futureValue.map(mkDeep)
)
def testCall[T](call: RestTestApi => Future[T])(implicit pos: Position): Future[Assertion] =
(call(proxy).wrapToTry, call(impl).catchFailures.wrapToTry).mapN { (proxyResult, implResult) =>
assert(proxyResult.map(mkDeep) == implResult.map(mkDeep))
}

def mkDeep(value: Any): Any = value match {
case arr: Array[_] => IArraySeq.empty[AnyRef] ++ arr.iterator.map(mkDeep)
Expand All @@ -53,72 +52,71 @@ abstract class RestApiTest extends AnyFunSuite with ScalaFutures with BeforeAndA
trait RestApiTestScenarios extends RestApiTest {
override implicit val patienceConfig: PatienceConfig = PatienceConfig(scaled(Span(10, Seconds)), scaled(Span(50, Millis)))

test("trivial GET") {
"trivial GET" in {
testCall(_.trivialGet)
}

test("failing GET") {
"failing GET" in {
testCall(_.failingGet)
}

test("JSON failing GET") {
"JSON failing GET" in {
testCall(_.jsonFailingGet)
}

test("more failing GET") {
"more failing GET" in {
testCall(_.moreFailingGet)
}

test("complex GET") {
"complex GET" in {
testCall(_.complexGet(0, "a/ +&", 1, "b/ +&", 2, "ć/ +&", Opt(3), 4, "ó /&f"))
testCall(_.complexGet(0, "a/ +&", 1, "b/ +&", 2, "ć/ +&", Opt.Empty, 3, "ó /&f"))
}

test("multi-param body POST") {
"multi-param body POST" in {
testCall(_.multiParamPost(0, "a/ +&", 1, "b/ +&", 2, "ć/ +&", 3, "l\"l"))
}

test("single body PUT") {
"single body PUT" in {
testCall(_.singleBodyPut(RestEntity(RestEntityId("id"), "señor")))
}

test("form POST") {
"form POST" in {
testCall(_.formPost("ó", "ą=ę", 42))
}

test("prefixed GET") {
"prefixed GET" in {
testCall(_.prefix("p0", "h0", "q0").subget(0, 1, 2))
}

test("transparent prefix GET") {
"transparent prefix GET" in {
testCall(_.transparentPrefix.subget(0, 1, 2))
}

test("custom response with headers") {
"custom response with headers" in {
testCall(_.customResponse("walue"))
}

test("binary request and response") {
"binary request and response" in {
testCall(_.binaryEcho(Array.fill[Byte](5)(5)))
}

test("large binary request and response") {
"large binary request and response" in {
testCall(_.binaryEcho(Array.fill[Byte](1024 * 1024)(5)))
}

test("body using third party type") {
"body using third party type" in {
testCall(_.thirdPartyBody(HasThirdParty(ThirdParty(5))))
}

test("close connection on monix task timeout") {
"close connection on monix task timeout" in {
Task
.traverse(List.range(0, Connections))(_ => Task.deferFuture(proxy.neverGet).timeout(CallTimeout).failed)
.map(_ => assertResult(expected = Connections)(actual = impl.counterValue())) // neverGet should be called Connections times
.runToFuture
.futureValue
}

test("close connection on monix task cancellation") {
"close connection on monix task cancellation" in {
Task
.traverse(List.range(0, Connections)) { i =>
val cancelable = Task.deferFuture(proxy.neverGet).runAsync(_ => ())
Expand All @@ -128,7 +126,6 @@ trait RestApiTestScenarios extends RestApiTest {
}
.map(_ => assertResult(expected = Connections)(actual = impl.counterValue())) // neverGet should be called Connections times
.runToFuture
.futureValue
}
}

Expand Down

0 comments on commit 9a35f65

Please sign in to comment.