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

是否可以在Scala中模拟/覆盖依赖项/导入?

宁卓
2023-03-14

我有一些代码如下所示:

package org.samidarko.actors

import org.samidarko.helpers.Lib

class Monitoring extends Actor {

  override def receive: Receive = {
    case Tick =>
       Lib.sendNotification()
    }
}

有没有办法从ScalaTest中模拟/存根Lib,就像使用nodejs的proxyquire一样?

我读到我可以使用依赖注入,但我宁愿不这样做

我唯一的选择是传递我的lib作为类参数吗?

class Monitoring(lib: Lib) extends Actor {

有什么建议可以让它更容易测试吗?谢啦

编辑:

泽维尔·吉奥特的回答是这个问题的一个有趣的方法,但是我选择改变代码来进行测试。

我将Lib作为参数传递,并使用mockito进行模拟,这使代码比隐藏范围更易于测试和维护。

共有2个答案

凤高翰
2023-03-14

这不是一个完整的答案(因为我不太了解AOP),但为了让您了解正确的方向,这可以通过名为AspectJ的Java库实现:

https://blog.jayway.com/2007/02/16/static-mock-using-aspectj/

https://www.cakesolutions.net/teamblogs/2013/08/07/aspectj-with-akka-scala

伪代码中的示例(不详细介绍):

class Mock extends MockAspect {
    @Pointcut("execution (* org.samidarko.helpers.Lib.sendNotification(..))")
    def intercept() {...}

}

这种方法的底层基础是动态代理:https://dzone.com/articles/java-dynamic-proxy.但是,您也可以模拟静态方法(可能您必须在模式中添加wordstatic)。

金宣
2023-03-14

这个答案只使用calatest,不影响源代码:

碱性溶液:

假设您有这个src类(您想要测试的类,并且您想要模拟依赖项):

package com.my.code

import com.lib.LibHelper

class MyClass() {
  def myFunction(): String = LibHelper.help()
}

以及此库依赖项(在测试MyClass时要模拟/覆盖此依赖项):

package com.lib

object LibHelper {
  def help(): String = "hello world"
}

其想法是在测试文件夹中创建一个类,该类将覆盖/隐藏库。该类将与要模拟的类具有相同的名称和相同的包。在src/test/scala/com/external/lib中,可以创建LibHelper。包含以下代码的scala

package com.lib

object LibHelper {
  def help(): String = "hello world - overriden"
}

通过这种方式,您可以用通常的方式测试代码:

package com.my.code

import org.scalatest.FunSuite

class MyClassTest extends FunSuite {
  test("my_test") {
    assert(new MyClass().myFunction() === "hello world - overriden")
  }
}

改进的解决方案,允许为每个测试设置模拟的行为:

以前的代码清晰简单,但是LibHelper的模拟行为对所有测试都是一样的。人们可能希望有一种LibHelper产生不同输出的方法。因此,我们可以考虑在LibHelper中设置一个可变变量,并在每次测试前更新该变量,以设置LibHelper的期望行为。(只有当LibHelper是一个对象时才有效)

隐藏的LibHelper(src/test/scala/com/外部/lib中的那个)应该替换为:

package com.lib

object LibHelper {

  var testName = "test_1"

  def help(): String =
    testName match {
      case "test_1" => "hello world - overriden - test 1"
      case "test_2" => "hello world - overriden - test 2"
    }
}

规模最大的类应该是:

package com.my.code

import com.lib.LibHelper

import org.scalatest.FunSuite

class MyClassTest extends FunSuite {
  test("test_1") {
    LibHelper.testName = "test_1"
    assert(new MyClass().myFunction() === "hello world - overriden - test 1")
  }
  test("test_2") {
    LibHelper.testName = "test_2"
    assert(new MyClass().myFunction() === "hello world - overriden - test 2")
  }
}

非常重要的精度,因为我们使用的是全局变量,所以强制scatest按顺序(而不是并行)运行测试是必须的。相关的scatest选项(将包含在build.sbt中)是:

parallelExecution in Test := false
 类似资料:
  • 问题内容: 在其中,您可以选择覆盖依赖项,并使其指向其他存储库,例如在以下https://github.com/kubermatic/glog- logrus 库中,您需要在Gopkg.toml文件中添加以下几行: 然后在代码库中。但是,在go模块中,我看不到这样的选择吗?这使我认为唯一的解决方案是将import更改为。 谢谢! 问题答案: 这就是指令的目的。 引用Wiki Go 1.11模块:我

  • 问题内容: 你能 声明这样 的函数吗? 然后像这样 重新声明 它… 这样可以覆盖函数吗? 可以吗 问题答案: 编辑 解决此答案未直接解决原始问题的评论。如果您是通过Google搜索到达的,请从此处开始 有一个名为override_function的函数可以实际使用。但是,由于此函数是Advanced PHP Debugger扩展的一部分,因此很难为生产使用提供参数。因此,我要说“否”,不可能以原始

  • 如果我有一个maven项目,它对A和B版本2.0有显式依赖,而A对B版本1.0有传递依赖。较新版本的B会覆盖较旧版本吗?我使用了maven Depencdy:解析目标,看起来旧版本的B没有解析。如果A与较新版本的B不兼容怎么办?或者如果A依赖于B版本2.0,而我的项目在运行依赖关系后对B版本1.0有显式依赖:解析目标,那么我看不到B的较新版本。那么如何解决这些依赖关系呢? 当我使用resolve

  • 问题内容: 在Java中是否可以覆盖Objects数组的toString? 例如,假设我创建了一个简单的类(由于这是一个普遍的问题,所以实际上是哪个类并不重要)。客户端一旦创建了一个数组并使用了它,是否有可能不打印该数组的地址,而是打印一个定制的? PS:当然,我不能只在类中重写它,因为它与单个实例有关。 问题答案: 不会。您当然可以创建一个静态方法User.toString(User []),但

  • 问题内容: 我有以下测试方法,该方法使用从包中导入的函数。 可以在golang中进行模拟吗? 问题答案: 是的,只需进行简单的重构即可。创建一个函数类型的变量,用初始化,并让您的包调用而不是: 在测试中,您可以为分配另一个功能,该功能是在测试中定义的,并且可以执行测试所需的功能。 例如:

  • 上面的匕首2.0当量是多少? 您可以在GitHub上看到我的项目及其单元测试。