当前位置: 首页 > 知识库问答 >
问题:

如何模拟Scala单例对象?

白子默
2023-03-14

我试图模拟Scala单例对象。特别是,我需要模拟对象play。应用程序编程接口。图书馆。ws。WS在服务组件(测试中的类)中使用。使用Mockito这是不可能的,测试执行会以以下方式失败:

[error]    MockitoException: : 
[error] Cannot mock/spy class play.api.libs.ws.WS$
[error] Mockito cannot mock/spy following:
[error]   - final classes
[error]   - anonymous classes
[error]   - primitive types  (GeolocationSpec.scala:18)

在这里阅读,Scalamock似乎允许这样做:

要模拟独立的单例对象,请使用org。斯卡拉莫克。注释。模拟对象

我的服务组件是这样的:

trait GeolocationService {
  def wsClient = WS
  def getPath(origin: Location, destination: Location): Future[Route]
}

class DefaultGeolocationService extends GeolocationService {

  val serviceProviderEndpoint = Play.current.configuration.getString("api.directions.endpoint")

  override def getPath(origin: Location, destination: Location): Future[Route] = {

    val params = Seq(
      "origin" -> s"${origin.lat},${origin.lon}",
      "destination" -> s"${destination.lat},${destination.lon}"
    );
    val resp = wsClient.url(serviceProviderEndpoint.get).withQueryString(params: _*).get()
    resp.map {
      // omitted code
    }
  }
}

我的build.sbt有所有这些依赖关系:

[...]
"org.scalatest" %% "scalatest" % "2.2.1",
"org.specs2" %% "specs2" % "2.3.13" % "test",
"org.scalamock" %% "scalamock-specs2-support" % "3.0.1" % "test",
"org.scalamock" %% "scalamock-scalatest-support" % "3.0.1" % "test",
"org.scalamock" %% "scalamock" % "3.0.1",
[...]

但是我找不到这个:org。斯卡拉莫克。注释。模拟对象

也许这也可以使用EasyMock和PowerMock实现,但我找不到任何Scala示例代码。

任何想法?

共有3个答案

阎烨
2023-03-14

我不想改变设计来适应这种限制。基本上,我能得到的就是改变设计,然后使用模拟框架

  //since mocking frameworks on SCALA is not support mocking singleton
  //hacks are either required to change the design or ...
  //I'd rather putting the mocking logic here by myself
  var testUser:Option[User] = None;

  def getCurrentUser(request: Request[Object]) = {
    if( testUser != None ){
    testUser;
  }

希望能有所帮助。

燕嘉熙
2023-03-14

不要嘲笑单身汉。让您的服务组件依赖于隐藏它的精简外观,而不是WS:

trait GeolocationService {
  def ws: (String, Seq[String]) => Promise[Response] = { (url, params) =>
    wsClient.url(serviceProviderEndpoint.get).withQueryString(params: _*).get()
  }
  def getPath(origin: Location, destination: Location): Future[Route]
}

在您的测试中,只需使用模拟覆盖ws方法,现在很容易创建:

val mockedWs = mock[(String, Seq[String]) => Promise[Response]]
// TODO specify mock's behavior here
val service = new DefaultGeolocationService() {
  override def ws = mockedWs
}
孙嘉悦
2023-03-14

使用ScalaMock 3模拟单例对象是不可能的,但是Paul Butcher希望在ScalaMock 4中重新引入此功能(参见http://paulbutcher.com/2014/04/15/scalamock-status-report/)

 类似资料:
  • 给定一个Kotlin单例对象和一个调用它的方法的乐趣

  • 问题内容: 我有一个Scala对象,需要在Java类中使用。 这是Scala对象 如何在Java中使用此Scala对象? 到目前为止,我已经尝试了以下操作,但未成功(编译错误): //返回一个没有用的字符串,因为我想要实际的Person对象 问题答案: 编辑 :一个工作示例(我检查过,它可以编译并工作):Scala: Java对应项:

  • 代码示例: 第二个问题--模拟scala对象,似乎需要使用其他方法来创建这样的服务。

  • 我如何创建/模拟Spark Scala数据帧与一个案例类嵌套在顶层? 我目前正在单元测试一个在上述模式中输出数据帧的函数。为了检查相等性,我使用了toDF(),不幸的是,它给出了一个在模拟数据帧中的“_id”为nullable=true的模式,从而使测试失败(注意,函数的“实际”输出对所有内容都为nullable=true)。 我还尝试以不同的方式创建模拟数据帧,这导致了错误:https://pa

  • 我正在尝试easyMock测试几个类/接口方法。方法,试图捕获参数,但得到一个或另一个错误。如果我只记录了一个期望值,它甚至不会捕获参数管道中的任何内容,如果我使用以下方法,我会得到如下错误代码。 结果是错误的 testFireChannelInitializer(com.obolus.generic.impl.DefaultChannelListenerTest)运行时间:3.812秒 你知道怎

  • 问题内容: 当我创建一个说类Employee的模拟对象时。它不调用Employee对象的构造函数。我知道Mockito在内部使用CGLIb和反射,创建了一个代理类,将该类扩展为模拟。如果未调用employee的构造函数,那么如何创建employee类的模拟实例? 问题答案: Mockito使用CGLib生成类对象。但是,要实例化此类对象,它使用Objenesis http://objenesis.