我正在使用Slick 2.1.0的包装类开发一个现有的代码库(我知道)。这个包装器有一个名为transaction
的方法,它是一个通用的 - 它需要一个(f: => T)
(所以它是通过名称传递)。我需要模拟这个类进行单元测试。我们也在使用Mockito 1.10.19(我知道),这不会让我嘲笑一个名字(我相信......)。所以我不得不实现构建这个包装类的底层特征。
当前的问题是:我想模仿这个transaction
方法,所以它什么都不做。我正在测试的代码在(f: => Unit)
中传递。所以我想实现这个方法来返回Future.Done
。 (我是否提到过我们使用的是Finagle而不是Scala期货?)但这种方法是通用的。我该如何正确专业化?
这是我目前的尝试:
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中没有正式的背景,我根本不理解这一点:How can one provide manually specialized implementations with Scala specialization?
答案 0 :(得分:2)
@specialized
不允许您提供专业化,它只是生成自己的专业化。链接问题中提供的答案需要更改签名。从问题来看,你似乎无法改变它,在这种情况下,你运气不好。如果你可以......你可能仍然不幸,这取决于这个代码的确切调用方式。
OTOH,"我想忽略f
的解决方案,但如果通用属于Future.Done
类型,则只能返回Unit
"更简单:
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.???
。