我目前正在研究Scala项目,并且在测试广泛使用Singleton对象的代码时遇到了困难。
我有像这样的单身人士:
object SomeSingleton {
def someFunction(s: String): String = s + "b"
}
在某个项目的某个地方,我将其用于我想测试的方法:
val s = SomeSingleton.someFunction("a")
我开发了新功能,我希望SomeSingleton.someFunction
在没有真正方法调用的情况下在测试中返回一些特定值,我在Java中使用Powermock做了这个,但我在Scala中找不到这样做的方法。
我知道如何仍然可以做到这一点,但它意味着将原始代码更改为:
object SomeSingleton extends SomeSingletonClass{}
class SomeSingletonClass {
// Whole logic from SomeSingleton moves here
def someFunction(s: String): String = s + "b"
}
现在,我可以将SomeSingleton
的使用替换为SomeSingletonClass
并正确模拟它。所以这是我的担忧,项目不小,它不是100%测试覆盖,我对Scala相对较新,所以我不确定,它会导致什么不良后果?这是一个可行的解决方案?由于这个原因,我不希望遗留代码在某个随机位置中断。
答案 0 :(得分:1)
鉴于你拥有的(遗留代码有很多单身人士),我认为你的解决方案可能还可以。我想在这里分享我的一些想法。
是的,介绍SomeSingletonClass
课程将有助于嘲笑课程,但缺点是它不再是单身人士。我可以很容易地做val newSingleton = new SomeSingletonClass()
,瞧,我已经创建了一个新对象。测试单例的最好方法是,直接测试单例。我猜你的单身人士会调用更多其他单身人士,而你并不想执行所有这些副作用。但要正确解决问题,您需要对代码进行广泛的重构。
PowerMock
是Java中非常强大的模拟工具(可能功能太大)。它可以模拟静态方法/单例的方法是修改字节代码。它适用于大多数情况,但是当它没有时,你完全不知道如何解决它。在我之前在亚马逊的工作中,我们曾经广泛使用过PowerMock,但是由于它的黑盒魔术,我们慢慢地远离它。帮助我们实现这一目标的一种方法是使用依赖注入,您可以轻松地在测试中注入模拟对象。
我可以看到您正在处理遗留代码,因此重写所有内容并不容易(例如,引入依赖注入,甚至是新的SomeSingletonClass
。在这里尝试)。我的建议是,您可能不应该花太多时间为遗留代码编写测试。相反,在编写新代码时,请尝试使其可测试,并根据需要重构遗留代码。