How to recreate ZIO layers in tests?

78 views Asked by At

I have a test suite containing 3 tests, like:

val test1 = test("should do smth") {
    for {
        service <- ZIO.service[MyCustomService]
        res <- service.doSmth
    } yield assertTrue(res.isEmpty)
}.provide(MyCustomServiceImpl.layer)

val test2 = test("should do smth else") {
    for {
        service <- ZIO.service[MyCustomService]
        res <- service.doSmthElse
    } yield assertTrue(res.size == 1)
}.provide(MyCustomServiceImpl.layer)

val test3 ...

During execution in each test I have the same MyCustomService instance (coz printing hashcode returns the same result in all tests). Since MyCustomService contains a cache inside, from time to time some of tests fails randomly. Does ZIO have some aspects like @DirtiesContext in Spring framework or maybe I write my tests using incorrect approach ?

I've tried to search through ZIO test aspects, but couldn't find smth applicable. Currently I use workaround clearing cache in the beginning of each test and use @@ sequential aspect.

1

There are 1 answers

0
Dima On

First of all, let me categorically state, that you are mistaken in your comment: it is not only absolutely fine, but also highly advisable to design and refactor as necessary your services in a way that makes them easier to test, and coupling with a cache seems to be violating the single responsibility principle, so it seems highly likely that your design would benefit of a refactor that was suggested in the comments.

But to answer your original question, it appears, that the problem is with a specific way of how MyCustomServiceImpl.layer is implemented, which you have not shown.

I tried to reproduce your problem like this:

object ZIOFooSpec extends ZIOSpecDefault {
   class Foo() { def identify = hashCode.toString } 
   object Foo  { val layer = ZIOLayer.succeed(new Foo()) }

   val t = test("Foo")(
     ZIO.serviceWithZIO[Foo](s => ZIO.log(s.identify)).map(_ => assertTrue(true))
   ).provide(Foo.layer)
   override def spec = suite(t, t, t) 
}

When I run this, it prints three different numbers.