Mocking a method which returns an fs2.Stream

蓝咒 提交于 2019-12-10 18:06:01

问题


Why isn't it possible to mock a method that returns an fs2.Stream with a Mockito mock?

Mockito is complaining that I am trying to return a FreeC instead of a Stream. Why is that and how can I get it working?

The following code:

import cats.effect.IO
import fs2.Stream
import org.mockito.Mockito.when
import org.scalatest.FlatSpec
import org.scalatest.mockito.MockitoSugar

trait MyTrait {
  def method: Stream[IO, Int]
}

class TestSpec extends FlatSpec with MockitoSugar {

  val m: MyTrait = mock[MyTrait]
  val emptyReturn: Stream[IO, Int] = Stream.emits(List.empty[Int])

  when(m.method).thenReturn(emptyReturn)

  ...
}

gives this error:

TestSpec:
TestSpec *** ABORTED ***
  org.mockito.exceptions.misusing.WrongTypeOfReturnValue: Stream cannot be returned by method()
method() should return FreeC
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
   Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
  at TestSpec.<init>(TestSpec.scala:15)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
  at java.lang.Class.newInstance(Class.java:442)
  at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:435)
  at sbt.TestRunner.runTest$1(TestFramework.scala:76)
  at sbt.TestRunner.run(TestFramework.scala:85)
  at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:202)
  ...

回答1:


Seems to be something weird going on with mockito's runtime inspection of the mock (MyTrait) and fs2.Stream being a value class of FreeC.

One solution (other than just not mocking) would be to force fs2.Stream to be boxed at runtime in your test implementation. I managed this by converting MyTrait into MyTrait[F[_]] and def method: Stream[IO, Int] into def method: F[Int]

Then you mock MyTrait[Stream[IO, ?]].

Hope this helps a bit


This has been fixed as of mockito-scala v1.0.3




回答2:


I'm not sure about the mockito side, but there's no need to use mocking at all;

val m: MyTrait = new MyTrait {
  def method: Stream[IO, Int] = Stream.emits(List.empty[Int]).covary[IO]
}


来源:https://stackoverflow.com/questions/49070901/mocking-a-method-which-returns-an-fs2-stream

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!