Scala伴侣对象经常被提议作为对象工厂。它们似乎在生产代码中很好用,但是插入模拟对象进行测试呢?伴随对象将不知道模拟对象,因此无法实例化它。
我想做这样的事情:
class Foo {}
object Foo {
def create():Foo = new Foo()
}
class FooCreator(factory:Foo) {
def this() = this(Foo)
...
factory.create()
...
}
class FooMock extends Foo {}
object FooMock extends Foo {
def create():Foo = new FooMock()
}
// in a test
val fooCreator = new FooCreator(FooMock)
这不起作用,因为无法扩展伴随对象。我不得不为两个伴侣对象创建一个工厂特征来混合:
trait FooFactory {
def create():Foo;
}
class Foo {}
object Foo extends FooFactory {
def create():Foo = new Foo()
}
class FooCreator(factory:FooFactory) {
def this() = this(Foo)
...
factory.create()
...
}
class FooMock extends Foo {}
object FooMock extends FooFactory {
def create():Foo = new FooMock()
}
// in a test
val fooCreator = new FooCreator(FooMock)
有更好的方法吗?创建工厂特性只是感觉不对,因为这是伴侣对象应该擅长的。 (请记住,Mock工件只有测试子系统才知道,所以我不能通过让对象Foo创建一个FooMock实例 - 生产代码中的常见模式来解决问题。)
答案 0 :(得分:3)
使用apply
方法而不是对象作为工厂,详见我的问题How to use companion factory objects as strategy?的答案
答案 1 :(得分:1)
您可能需要查看ScalaMock,这是Scala的模拟框架,可以(除其他外)模拟对象创建(编译器调用)。这正是它要解决的问题之一。