From 9a35f65cb18cb59c03541fb12176586a4e97794d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Kozak?= Date: Mon, 23 Dec 2024 15:06:17 +0100 Subject: [PATCH] Refactor REST API tests to use consistent async syntax 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. --- .../io/udash/rest/SttpRestCallTest.scala | 21 +++++--- .../scala/io/udash/rest/RestApiTest.scala | 51 +++++++++---------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/rest/.jvm/src/test/scala/io/udash/rest/SttpRestCallTest.scala b/rest/.jvm/src/test/scala/io/udash/rest/SttpRestCallTest.scala index 1c5d2d658..f77fa0ded 100644 --- a/rest/.jvm/src/test/scala/io/udash/rest/SttpRestCallTest.scala +++ b/rest/.jvm/src/test/scala/io/udash/rest/SttpRestCallTest.scala @@ -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)) diff --git a/rest/src/test/scala/io/udash/rest/RestApiTest.scala b/rest/src/test/scala/io/udash/rest/RestApiTest.scala index 85d7b0045..50142a219 100644 --- a/rest/src/test/scala/io/udash/rest/RestApiTest.scala +++ b/rest/src/test/scala/io/udash/rest/RestApiTest.scala @@ -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 @@ -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) @@ -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(_ => ()) @@ -128,7 +126,6 @@ trait RestApiTestScenarios extends RestApiTest { } .map(_ => assertResult(expected = Connections)(actual = impl.counterValue())) // neverGet should be called Connections times .runToFuture - .futureValue } }