I have the following function, that I want to test:
def people(id: Int): RIO[R, People]
This function returns People if there is one for that id
, resp. fails if not, like:
IO.fail(ServiceException(s"No People with id $id"))
The happy case works, like:
suite("Get a Person for an ID") (
testM("get Luke Skywalker") {
for {
peopleRef <- Ref.make(Vector(People()))
luke <- Swapi.>.people(1).provide(Test(peopleRef))
} yield assert(luke, equalTo(People()))
},
But how can I test the failure case? I tried different things, mostly the types do not match. Here is an attempt:
testM("get not existing People") {
(for {
peopleRef <- Ref.make(Vector(People()))
failure = Swapi.>.people(2).provide(Test(peopleRef))
} yield assertM(failure, fail(Cause.die(ServiceException(s"No People with id 2")))
}
)
I think you've definitely got it. The only thing I would add for others with similar questions is your example also involves an environment type, which is a great topic for discussion but somewhat independent of how to test that an effect fails as expected using ZIO Test.
I've included below a minimal example of how to test that an effect fails as expected. As mentioned above, you would call run
on the effect to get an exit value and then use Assertion.fails
to assert that the effect fails with a checked exception, Assertion.dies
to assert that the effect fails with an unchecked exception, or Assertion.interrupted
to test that an effect was interrupted.
Also note that you do not have to use include equalTo("fail")
. If all you care about is that the effect failed you can just use fails(anything)
. If you are testing that an effect dies with a specified exception you can do something like dies(isSubtype[IllegalArgumentException])
.
Hope this helps!
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail")
} yield assert(result, fails(equalTo("fail")))
}
)
)
With the help of @adamfraser in the ZIO-Chat:
Basically call run on your failing effect and then assert that it is a failure with Assertion.fails. Or Assertion.dies if it is an unchecked exception.
I think I have now a nice solution.
testM("get not existing People") {
for {
peopleRef <- Ref.make(Vector(People()))
failure <- Swapi.>.people(2).provide(Test(peopleRef)).run
} yield assert(
failure,
fails(equalTo(ServiceException("No People with id 2")))
)
}
Other solutions are still welcome.
You could also flip the error and result channels:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail("fail").flip
} yield assert(result, equalTo("fail"))
}
)
)
Here's another compact variant using assertM
for ZIO 1.0:
import zio._
import zio.test.Assertion.{equalTo, fails}
import zio.test._
object ExampleSpec extends DefaultRunnableSpec {
def spec = suite("ExampleSpec")(
testM("Example of testing for expected failure") {
assertM(ZIO.fail("fail").run)(fails(equalTo("fail")))
}
)
}
In ZIO 2.0 the test looks very similar:
import zio._
import zio.test._
import zio.test.Assertion.{equalTo, fails}
object ExampleSpec extends ZIOSpecDefault {
def spec = suite("ExampleSpec ZIO 2.0")(
test("Example of testing for expected failure in ZIO 2.0") {
assertZIO(ZIO.fail("fail").exit)(fails(equalTo("fail")))
}
)
}
if your error is throwable, the equalsTo
fails when it runs against a running effect so you have to use isSubtype
Assertion in order to check do you receive your correct error and it is a little More tricky:
import zio.test._
import zio.test.Assertion._
import zio.ZIO
object ExampleSpec
extends DefaultRunnableSpec(
suite("ExampleSpec")(
testM("Example of testing for expected failure") {
for {
result <- ZIO.fail(new NoSuchElementException).run
} yield assert(result, fails(isSubtype[NoSuchElementException](anything)))
}
)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With