在需要并发和Timer类型的类实例的测试中使用哪种类型?

时间:2019-01-24 07:54:10

标签: scala functional-programming scala-cats

考虑以下示例:

import cats.Functor
import cats.effect.{Concurrent, Timer}
import cats.syntax.functor._
import fs2.Stream

import scala.concurrent.duration._

class FetchAndSum[F[_]: Timer: Concurrent: Functor](fetch: List[String] => F[List[Int]]) {

  def run(inputs: List[String]): F[Int] =
    Stream
      .emits(inputs)
      .covary[F]
      .groupWithin(20, 10.millis)
      .mapAsync(10)(chunk => fetch(chunk.toList))
      .flatMap(Stream.emits)
      .reduce(_ + _)
      .compile
      .last
      .map(_.getOrElse(0))
}

在生产中,这是通过IO Monad实例化的。

在测试中,我想测试调用fetch函数的次数。如果F[_]仅需要一个Functor实例,我可以简单地使用Writer monad来做到这一点。

由于fs2的mapAsyncgroupedWithinF[_]还必须具有TimerConcurrent的实例,这些当然在{ {1}}。

我可以使用哪种数据类型来进行功能测试?

我考虑过以某种方式将WriterIO结合起来,例如Writer,但是如果不重新声明type IOWriter[A] = IO[Writer[Int, A]]的所有类型类实例,我将无法完成这项工作。

有什么可以让我实现而不必重新声明所有类型类实例的东西吗?

1 个答案:

答案 0 :(得分:4)

IORef一起使用:

val numsExecuted: IO[Int] = for {
  ref <- Ref[IO].of(0)
  fetch = (l: List[String]) => ref.update(_ + 1).as(???)
  _ <- new FetchAndSum[IO](fetch).run(???)
  x <- ref.get
} yield x

您还可以结合使用WriterIO。这种构造称为Writer monad转换器(type IOWriter[A] = cats.data.WriterT[IO, A]),应立即使用Concurrent / Timer / Monad / etc。实例。