我正在使用Slick 2.1.0(我知道)周围的包装器类处理现有的代码库。这个包装器有一个名为transaction
的方法,它是泛型的——它接受一个(f: => T)
(所以它是按名称传递的)。我需要模拟这个类进行单元测试。我们还使用了Mockito 1.10.19(我知道),它不会让我按名称模拟pass(我相信…)。所以我一直在实现这个包装类所基于的底层特性。
直接的问题是:我想模拟这个transaction
方法,这样它就什么都不做了。我正在测试的代码在(f: => Unit)
中通过。所以我想实现这个方法来返回一个Future.Done
。(我有没有提到我们使用的是Finagle而不是Scala futures?)但这个方法是通用的。如何正确地进行专业化?
这是我目前的尝试:
val mockDBM = new DatabaseManager {
override def transaction[@specialized(Unit) T](f: => T): Future[T] = Future.value(f)
def transaction(f: => Unit): Future[Unit] = Future.Done
}
当然,我在编译时得到了一个have same type after erasure
错误。显然,我不知道@specialized
是如何工作的。
我该怎么办?也许我可以用Mockito?或者我需要学习专门化泛型方法的实际含义?
我发现了这一点,这可能包含了答案,但我没有FP的正式背景,我根本不想知道:如何用Scala专业化来提供手动专业化的实现?
@specialized
不允许您提供专业化,它只是生成自己的。联系问题中提供的答案需要更改签名。从这个问题来看,你似乎无法改变它,在这种情况下,你运气不好。如果可以的话。。。您可能仍然运气不佳,这取决于该代码的调用方式。
OTOH,"我想忽略f
,但如果泛型是针对Unit
类型的,则只能返回Future.Done
"的解决方案要简单得多:
class Default[A] {
var x: A = _
}
object Default {
def apply[A]() = (new Default[A]).x
}
val mockDBM = new DatabaseManager {
override def transaction[T](f: => T): Future[T] = {
Future.value(Default(x))
}
}
假设你需要一个成功的未来,但不在乎价值,也就是说;如果您只需要任何的未来,override def transaction[T](f: => T): Future[T] = Future.???
。