Created
April 7, 2021 08:52
-
-
Save mostr/6b53fc13a686c0c358f8c8646f531263 to your computer and use it in GitHub Desktop.
ZIO test clock + scheduled tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package scheduler | |
import zio.clock.Clock | |
import zio.duration.durationInt | |
import zio.logging.Logging | |
import zio.test.Assertion.equalTo | |
import zio.test.environment.TestEnvironment | |
import zio.test.{DefaultRunnableSpec, ZSpec} | |
import zio.{Has, Ref, ZIO} | |
/* | |
Testing ZIO-based repeated tasks. It works fine locally, but when there is logging within the task it stops working under test. | |
It looks like it somehow holds execution after first iteration, because adding `fork` to logging statement within `doWorkLogging` makes test pass | |
*/ | |
object SimpleSpec extends DefaultRunnableSpec { | |
private val doWorkLogging = for { | |
_ <- ZIO.accessM[Has[Ref[Long]]](_.get.update(_ + 1)) | |
now <- zio.clock.instant | |
_ <- zio.logging.log.info(s"Run $now") | |
} yield () | |
private val doWorkConsole = for { | |
_ <- ZIO.accessM[Has[Ref[Long]]](_.get.update(_ + 1)) | |
now <- zio.clock.instant | |
_ <- zio.console.putStrLn(s"Run $now") | |
} yield () | |
private val logging = Logging.console() | |
override def spec: ZSpec[Environment, Any] = suite("simple test")( | |
testM("logging + delay work with Clock.live") { | |
val counter = Ref.make(0L).toLayer | |
val looper = doWorkLogging *> (zio.UIO.unit.delay(2.seconds) *> doWorkLogging).forever | |
(for { | |
f <- looper.fork | |
_ <- zio.clock.sleep(5.seconds) | |
ref <- ZIO.service[Ref[Long]] | |
count <- ref.get | |
_ <- f.interrupt | |
} yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer(Clock.live ++ logging ++ counter) | |
}, | |
// Why is this one failing with count = 1? | |
testM("logging + delay don't work with TestEnvironment") { | |
val counter = Ref.make(0L).toLayer | |
val looper = doWorkLogging *> (zio.UIO.unit.delay(2.seconds) *> doWorkLogging).forever | |
(for { | |
f <- looper.fork | |
_ <- zio.test.environment.TestClock.adjust(5.seconds) | |
ref <- ZIO.service[Ref[Long]] | |
count <- ref.get | |
_ <- f.interrupt | |
} yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer[TestEnvironment](logging ++ counter) | |
}, | |
// And why this one (with logging replaced with console) works then? | |
testM("console + delay work with TestEnvironment") { | |
val counter = Ref.make(0L).toLayer | |
val looper = doWorkConsole *> (zio.UIO.unit.delay(2.seconds) *> doWorkConsole).forever | |
(for { | |
f <- looper.fork | |
_ <- zio.test.environment.TestClock.adjust(5.seconds) | |
ref <- ZIO.service[Ref[Long]] | |
count <- ref.get | |
_ <- f.interrupt | |
} yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer[TestEnvironment](logging ++ counter) | |
}, | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment