模拟 returns 和 fs2.Stream 的方法
Mocking a method which returns an fs2.Stream
为什么不能使用 Mockito 模拟来模拟 return 是 fs2.Stream 的方法?
Mockito 抱怨说我正在尝试 return FreeC 而不是 Stream。为什么会这样,我怎样才能让它发挥作用?
以下代码:
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)
...
}
出现此错误:
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(TestFramework.scala:76)
at sbt.TestRunner.run(TestFramework.scala:85)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:202)
...
我不确定 mockito 方面,但根本不需要使用 mocking;
val m: MyTrait = new MyTrait {
def method: Stream[IO, Int] = Stream.emits(List.empty[Int]).covary[IO]
}
mockito 对模拟 (MyTrait) 的运行时检查似乎有些奇怪,fs2.Stream 是 FreeC 的值 class。
一个解决方案(除了不模拟之外)是强制 fs2.Stream 在您的测试实现中在运行时进行装箱。
我通过将 MyTrait 转换为 MyTrait[F[_]] 并将 def 方法:Stream[IO, Int] 转换为 def 方法:F[Int]
来实现这一点
然后你模拟 MyTrait[Stream[IO, ?]].
希望对您有所帮助
自 mockito-scala v1.0.3 起已修复此问题
为什么不能使用 Mockito 模拟来模拟 return 是 fs2.Stream 的方法?
Mockito 抱怨说我正在尝试 return FreeC 而不是 Stream。为什么会这样,我怎样才能让它发挥作用?
以下代码:
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)
...
}
出现此错误:
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(TestFramework.scala:76)
at sbt.TestRunner.run(TestFramework.scala:85)
at sbt.TestFramework$$anon$$anonfun$$init$$$anonfun$apply.apply(TestFramework.scala:202)
...
我不确定 mockito 方面,但根本不需要使用 mocking;
val m: MyTrait = new MyTrait {
def method: Stream[IO, Int] = Stream.emits(List.empty[Int]).covary[IO]
}
mockito 对模拟 (MyTrait) 的运行时检查似乎有些奇怪,fs2.Stream 是 FreeC 的值 class。
一个解决方案(除了不模拟之外)是强制 fs2.Stream 在您的测试实现中在运行时进行装箱。 我通过将 MyTrait 转换为 MyTrait[F[_]] 并将 def 方法:Stream[IO, Int] 转换为 def 方法:F[Int]
来实现这一点然后你模拟 MyTrait[Stream[IO, ?]].
希望对您有所帮助
自 mockito-scala v1.0.3 起已修复此问题