如何模拟 MVar2 make 方法

How to mock MVar2 make method

我在单元测试(使用 mockito)中模拟 MVar2 方法 make 时遇到问题。

我试过这个:

private val sq = mock[MVar2[IO, String]]

当我尝试像这样模拟方法时:

when(sq.take).thenReturn(
      "testString".pure[IO],
      IO.never
    )

我在测试中得到了无限循环。

我很确定我可以像这样嘲笑它。

调用make的实际代码是:

  def run: F[Unit] =
    fs2.Stream
      .repeatEval[F, String](signalQ.take)
      .map(encode)
      .unNone
      .evalTap(logMessage)
      .evalMap(send)
      .compile
      .drain

我看到两个问题。

首先,没有理由模拟 IO。你几乎可以做到这一点:

// define this wherever you create sq 
val sq = MVar2[IO, String]
// then DI sq and
sq.put("testString") >> run

那么第二件事,.repeatEval(io) 是如何工作的?每次流需要另一个元素时,它都会重复调用 io。所以起初它会用你的模拟评估 io 到:

"testString".pure[IO]

这会将第一个元素计算为 "testString",然后计算为

IO.never

这意味着第二个元素永远不会出现,因为这个 io 永远不会 return - 既不是值也不是异常。如您所见,您的流停止了。 (这将符合规范,但显然不是您想要的)。

如果你想在值存在时获取 Some(string),在值不存在时获取 None(在 None 上终止流)你应该尝试:

def run: F[Unit] =
  fs2.Stream
    .repeatEval[F, Option[String]](signalQ.tryTake)// <-- try to get None on empty
    .unNoneTerminate // <-- terminate on None
    .map(encode)
    .evalTap(logMessage)
    .evalMap(send)
    .compile
    .drain