Scala中对象的Mockito

Scala中对象的Mockito,scala,object,mockito,Scala,Object,Mockito,我正在使用Scala 2.10、specs2和Mockito。我想模拟scala.io.Source.fromURL()。问题似乎在于fromURL()是中的一个函数 这是单元测试中非常简单的模拟。为什么不起作用 谢谢 您可以按如下方式尝试监视它,而不是模拟它: val m = spy(io.Source) val m = mock[io.Source.type] 或者你也可以这样嘲笑它: val m = spy(io.Source) val m = mock[io.Source.type

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

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


谢谢

您可以按如下方式尝试
监视它,而不是模拟它:

val m = spy(io.Source)
val m = mock[io.Source.type]
或者你也可以这样嘲笑它:

val m = spy(io.Source)
val m = mock[io.Source.type]
但是,您如何在正在测试的类中使用
源代码?如果您有这样一个示例类:

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
  }
}
然后,为了利用模拟/监视,您必须按照如下方式构造类:

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世界中,对对象的调用对于单元测试来说也很麻烦。但是,如果您遵循上面的代码,您应该能够在类中正确地模拟出基于对象的依赖关系。

几年后,上述答案并不像其他人指出的那样有效

然后,您将看到
scala.io.Source
对象

我可以模拟final/private方法或类吗?这是不受支持的,因为使用宏生成的mock被实现为mock类型的子类。因此,不能重写私有方法和final方法。您可能希望尝试在代码中使用适配器或façade使其可测试。最好针对trait/接口而不是具体的实现进行测试。有些库支持这种模拟,例如PowerMock。请注意,这种模拟涉及字节码操作,这有可能使您的测试与实际实现产生偏差

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

//原始函数
def afuncthatsusesource()={
val source=scala.io.source(“127.0.0.1:8080/…”)
val result=source.mkString
尝试(source.close())
结果
}
//接受'scala.io.Source.fromURL'作为参数的测试友好函数
def aTestFriendlyFunc(makeApiCall:String=>BufferedSource)={
val source=makeApiCall(“127.0.0.1:8080/…”)
val result=source.mkString
尝试(source.close())
结果
}
....
//测试规范
def testyMcTesterson=()=>{
val makeApiCall=mockFunction[字符串,缓冲源]
makeApiCall.expected(“某物…”)
.returns(new BufferedSource(new ByteArrayInputStream(“returns something”.getBytes)))
aTestFriendlyFunc(makeApiCall)应等于“返回某物”
}

好消息!使用最新的1.16版本的
mockitoscala
,您现在可以模拟scala
object
s

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

mock-maker-inline 
例如:

objectfoooobject{
def simpleMethod:String=“未模拟!”
}
“模拟”应该是{
中的“存根对象方法”{
FooObject.simpleMethod应该是“不被嘲笑!”
withObjectMocked[FooObject.type]{
FooObject.simpleMethod返回“mocked!”
//或
当(FooObject.simpleMethod)返回“mocked!”
FooObject.simpleMethod应该是“mocked!”
}
FooObject.simpleMethod应该是“不被嘲笑!”
} 
}

请参阅:

回答得很好!我是Scala的新手,我觉得它很麻烦。正如一位朋友所说,它看起来类似于依赖注入模式。为什么模仿io.BufferedSource的mkString不起作用?这是一个实例方法:我得到一个错误:Mockito无法模拟/间谍以下:-最终类-匿名类-原语类型是否可以对对象执行类似操作?嘿@GismoRanas如何解决此问题我面临相同的错误。这与PowerMock模拟静态的方式不同;后者通过修改原始对象的字节码来实现,而在我的测试中,似乎
withObjectMocked
通过子类化创建了一个新实例。除非注入对mock的引用,否则测试中的代码仍将引用原始对象。