2

Let's assume I have code such as this:

final case class CustomException(errorCode: Int, id: UUID) extends Throwable

val logic: ZIO[Any, Throwable, Unit] = ???

I would like to use ZIO Test to check for a specific error case

val checkForTimeout = testM("Logic should time out") {
  for {
    result <- logic.flip
  } yield assert(result, isSubtype[CustomException](???))
}

What I would like to do is check the errorCode field for a specific value. But it seems the existing combinators in ZIO Test only allow me to check the the full object. I would like to only check for _.errorCode while ignoring _.id, which means equalTo is not a good enough combinator for this use case.

How would I go about addressing this?

2 Answers2

6

You can use Assertion.hasField, which lets you "zoom in" on one part of a larger structure, to do this.

val checkForTimeout = testM("Logic should time out") {
  for {
    result <- logic.flip
  } yield assert(
      result,
      isSubtype[CustomException](hasField("errorCode", _.errorCode, equalTo(1)))
    )
}
Adam Fraser
  • 809
  • 5
  • 4
2

The simplest thing would be to adjust the signature of logic.

val logic: ZIO[Any, CustomException, Unit] = ???

Now you can do something like:

val checkForTimeout = testM("Logic should time out") {
    for {
      result: CustomException <- logic.flip
    } yield assert(result.errorCode, equalTo(543))
}

If not you can still cast the result:

val checkForTimeout = testM("Logic should time out") {
    for {
      th <- logic.flip
      result = th.asInstanceOf[CustomException]
    } yield assert(result.errorCode, equalTo(543))
}
pme
  • 14,156
  • 3
  • 52
  • 95
  • This would indeed work. But I cannot change the signature of `logic` and would like to avoid the cast. Adam's answer involving `hasField` is what I had hoped to find. – Tim Steinbach Dec 31 '19 at 18:30