Home > Enterprise >  How to mock MVar2 make method
How to mock MVar2 make method

Time:12-15

I'm having trouble mocking the MVar2 method make in my Unit test (using mockito).

I tried this:

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

and when I tried to mock the method like:

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

I get the infinite loop in the test.

I was positive I could mock it like this.

The actual code calling the make is:

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

CodePudding user response:

I see two issues.

The first thing, there is no reason to mock IO. You can pretty much do this:

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

Then the second thing, how does .repeatEval(io) works? It calls io repeatedly, every time the stream needs another element. So at first it would evaluate io with your mock to:

"testString".pure[IO]

which would compute the first element to "testString" and later to

IO.never

which means that the second element would never appear as this io would never return - neither value nor exception. And your stream halts as you can see. (Which would be according to the spec but apparently not what you want).

If you wanted to get Some(string) if value is present and None if it's absent (to terminate stream on None) you should try:

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
  • Related