Scala中对象的Mockito



我使用的是Scala 2.10、specs2和Mockito。我想模拟scala.io.Source.fromURL((。问题似乎是fromURL((是io.Source对象中的一个函数。

val m = mock[io.Source]
m.fromURL returns io.Source.fromString("Some random string.")

这是单元测试中非常简单的模拟。为什么它不起作用?

谢谢!

与其嘲笑它,不如按如下方式尝试spying

val m = spy(io.Source)

或者你可以嘲笑它如下:

val m = mock[io.Source.type]

但是,在测试的类中,你是如何使用Source的呢?如果你有一个这样的示例类:

class MyClass{
  def foo = {
    io.Source.doSomething //I know doSomething is not on Source, call not important
  }
}

然后,为了利用嘲笑/间谍,你必须这样构建你的类:

class MyClass{
  val source = io.Source
  def foo = {
    source.doSomething
  }
}

然后你的测试必须看起来像这样:

val mockSource = mock[io.Source.type]
val toTest = new MyClass{
  override val source = mockSource
}

在Java世界中,静态方法是嘲讽的祸根。在Scala的世界里,对对象的调用对于单元测试来说也很麻烦。但是,如果您遵循上面的代码,您应该能够在类中正确地模拟出基于对象的依赖关系。

好消息!有了mockito-scala的最新1.16版本,您现在可以模拟scala object s。

要启用ObjectMocked功能,必须创建文件src/test/resources/mockito-extensions/org.mockito.plugins.LockMaker,其中包含一行:

mock-maker-inline 

示例:

object FooObject {   
  def simpleMethod: String = "not mocked!"
}
"mock" should {
  "stub an object method" in {
    FooObject.simpleMethod shouldBe "not mocked!"
    withObjectMocked[FooObject.type] {
      FooObject.simpleMethod returns "mocked!"
      //or
      when(FooObject.simpleMethod) thenReturn "mocked!"
      FooObject.simpleMethod shouldBe "mocked!"
    }
    FooObject.simpleMethod shouldBe "not mocked!"
  } 
}

请参阅:https://github.com/mockito/mockito-scala#mocking-scala对象

多年后,上面的答案并没有像其他人所指出的那样奏效。

并且不能模拟scala.io.Source对象。

我可以模拟final/private方法或类吗?这是不受支持的,因为用宏生成的mock被实现为要mock的类型的子类。因此,私有方法和最终方法不能被重写。您可能想尝试在代码中使用适配器或外观,使其可测试。最好针对特性/接口进行测试,而不是针对具体实现进行测试。有一些库支持这种嘲讽,比如PowerMock。请注意,这种嘲讽涉及字节码操作,这有可能导致您的测试与实际实现产生双重差异。

因此,我所做的是将scala.io.Source.fromUrl()抽象为函数参数,并在测试中传递模拟函数。

  // original func
  def aFuncThatUsesSource() = {
    val source = scala.io.Source("127.0.0.1:8080/...")
    val result = source.mkString
    Try(source.close())
    result
  }
  // test friendly func that accepts `scala.io.Source.fromURL` as arg
  def aTestFriendlyFunc(makeApiCall: String => BufferedSource) = {
    val source = makeApiCall("127.0.0.1:8080/...")
    val result = source.mkString
    Try(source.close())
    result
  }
....
  // test spec
  def testyMcTesterson = () => {
    val makeApiCall = mockFunction[String, BufferedSource]
    makeApiCall.expects("something...")
      .returns( new BufferedSource(new ByteArrayInputStream("returns something".getBytes)) )
    aTestFriendlyFunc(makeApiCall) shouldEqual "returns something"
  }

相关内容

  • 没有找到相关文章

最新更新