【问题标题】:Mocking a method which returns an fs2.Stream模拟返回 fs2.Stream 的方法
【发布时间】:2018-03-02 14:13:12
【问题描述】:

为什么不能用 Mockito 模拟来模拟返回 fs2.Stream 的方法?

Mockito 抱怨我试图返回 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$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)
  ...

【问题讨论】:

    标签: scala mockito fs2


    【解决方案1】:

    我不确定 mockito 方面,但根本不需要使用 mocking;

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

    【讨论】:

      【解决方案2】:

      mockito 对 mock (MyTrait) 的运行时检查和 fs2.Stream 作为 FreeC 的值类似乎有些奇怪。

      一种解决方案(不仅仅是不模拟)是在您的测试实现中强制 fs2.Stream 在运行时装箱。 我通过将 MyTrait 转换为 MyTrait[F[_]] 和 def 方法来管理它: Stream[IO, Int] 转换为 def 方法:F[Int]

      然后你模拟 MyTrait[Stream[IO, ?]]。

      希望对你有所帮助


      这已从 mockito-scala v1.0.3 开始修复

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-05
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        • 2011-09-30
        • 2014-09-30
        相关资源
        最近更新 更多