请原谅这个问题的长度.
我经常需要在我的代码的一层创建一些上下文信息,并在其他地方使用该信息.我通常发现自己使用隐式参数:
def foo(params)(implicit cx: MyContextType) = ...
implicit val context = makeContext()
foo(params)
Run Code Online (Sandbox Code Playgroud)
这是有效的,但是需要隐式参数传递很多,在介入函数的布局之后污染图层的方法签名,即使他们自己并不关心它.
def foo(params)(implicit cx: MyContextType) = ... bar() ...
def bar(params)(implicit cx: MyContextType) = ... qux() ...
def qux(params)(implicit cx: MyContextType) = ... ged() ...
def ged(params)(implicit cx: MyContextType) = ... mog() ...
def mog(params)(implicit cx: MyContextType) = cx.doStuff(params)
implicit val context = makeContext()
foo(params)
Run Code Online (Sandbox Code Playgroud)
我发现这种方法很难看,但它确实有一个优点:它的类型安全.我肯定知道mog会收到正确类型的上下文对象,或者它不会编译.
如果我可以使用某种形式的"依赖注入"来定位相关的上下文,它将减轻混乱.引号表明这与Scala中常见的依赖注入模式不同.
起点foo和终点mog可以存在于系统的非常不同的级别.例如,foo可能是用户登录控制器,mog可能正在进行SQL访问.可能有许多用户同时登录,但只有一个SQL层实例.每次mog由不同的用户调用时,需要不同的上下文.因此,上下文不能被烘焙到接收对象中,也不想以任何方式合并这两个层(如Cake Pattern).我还宁愿不依赖像Guice或Spring这样的DI/IoC库.我发现它们很重,不太适合Scala.
所以我认为我需要的东西是mog让它在运行时为它检索正确的上下文对象,有点像在ThreadLocal其中有一个堆栈: …
我有一个Scala对象,它包含一些实用程序功能.这些函数由同一对象中存在的其他函数或其他类/对象调用.是否可以模拟这个对象或函数,以便我可以对它们被调用的类进行单元测试.
例:
object Util {
def methodA() = {
//other code
methodB()
//other code
}
def methodB() = {
//other code
methodC()
//other code
}
def methodC() = { ... }
}
Run Code Online (Sandbox Code Playgroud)
在这里,我从另一个类调用对象函数
class Data {
//other code
def call() = {
//other code
Util.methodA()
//other code
}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能对类Data的函数call()进行单元测试?在Java中,我可以为Util创建一个模拟对象,并设置对methodA()调用的期望,但这在Scala中是不可能的,因为没有模拟库支持模拟Scala对象.
关于 ScalaMock 模拟(同伴)对象和构造函数的能力,存在一些相互矛盾的说法。ScalaMock页面逐步说明
它还可以模拟:
另一方面,路线图告诉我:
2016 年第一季度 - ScalaMock 4 一旦 scala.meta 可用,我们计划开始开发 ScalaMock 4。如果 scala.meta 兑现其承诺,ScalaMock 4 应该能够模拟任何特征,无论其类型有多复杂。
此外,我们预计它还将支持:
那么,什么是正确的呢?当前版本(ScalaMock 3.2)是否能够模拟对象和构造函数?