Я хотел бы измерить прошедшее время внутри контейнера ввода-вывода. Это относительно легко сделать с помощью простых вызовов или фьючерсов (например, что-то вроде кода ниже)
class MonitoringComponentSpec extends FunSuite with Matchers with ScalaFutures {
import scala.concurrent.ExecutionContext.Implicits.global
def meter[T](future: Future[T]): Future[T] = {
val start = System.currentTimeMillis()
future.onComplete(_ => println(s"Elapsed ${System.currentTimeMillis() - start}ms"))
future
}
def call(): Future[String] = Future {
Thread.sleep(500)
"hello"
}
test("metered call") {
whenReady(meter(call()), timeout(Span(550, Milliseconds))) { s =>
s should be("hello")
}
}
}
Но не уверен, как обернуть вызов ввода-вывода
def io_meter[T](effect: IO[T]): IO[T] = {
val start = System.currentTimeMillis()
???
}
def io_call(): IO[String] = IO.pure {
Thread.sleep(500)
"hello"
}
test("metered io call") {
whenReady(meter(call()), timeout(Span(550, Milliseconds))) { s =>
s should be("hello")
}
}
Спасибо!





Cats-effect имеет реализацию Часы, которая позволяет измерять чистое время, а также внедрять свои собственные реализации для тестирования, когда вы просто хотите имитировать течение времени. Пример из их документации:
def measure[F[_], A](fa: F[A])
(implicit F: Sync[F], clock: Clock[F]): F[(A, Long)] = {
for {
start <- clock.monotonic(MILLISECONDS)
result <- fa
finish <- clock.monotonic(MILLISECONDS)
} yield (result, finish - start)
}
Это не совсем эквивалентно реализации OP
Future, хотяFuture.onCompleteможет привести к сбою времени.