假设我正在测试一个方法,它依赖于一个名为 WS(Web 服务)的(导入的)单例实例,它有一个方法url(url: String),它接受一个 URL 并返回一个请求。
def doRequest(url: String): Future[Response] = {
val request = WS.url(url)
for {
response <- request.post(params)
} yield {
val res: JsResult[MyResult] = response.json.validate[MyResult]
res.getOrElse(throw new NotSupportedException)
}
}
我希望能够注入 WS 依赖项,这样我的单元测试就不需要实际的出站 http 请求,而是可以依赖于模拟 WS 实例。
这对我来说是一个挑战,因为虽然单例在技术上确实有一个类型 (Class[WS.type]),但是当将单例绑定到需要 Class[WS.type] 的 val 时,WS 的属性和方法会丢失。这意味着我不能简单地使用简单的蛋糕图案,如下所示:
trait WSComponent {
val ws: Class[_ <: WS.type]
}
object ApplicationContext extends WSComponent {
val ws = WS
}
object TestContext extends WSComponent {
val ws = mock[WS]
}
如果我这样做,然后在任一上下文中调用 WS 的方法,我会得到一个编译错误,即 Class[_ <: WS.type] 没有调用(例如)url() 的方法。
出于类似的原因(基本上,单例对象没有类型——即使它们有——),我不能提供一个采用 WS.type 的隐式参数,因为我将再次丢失方法和在单例对象上声明的属性。
有哪些方法可以注入对单例对象的依赖项?我喜欢为 DI 使用 cake 模式,但它在我的代码中引入了相当多的样板,因此理想的解决方案不会将代码与过多的样板混合在一起。
提前感谢您的任何建议。