通过扩展工厂特征将Scala伴随对象用作工厂。好的解决方案

时间:2011-11-27 19:40:02

标签: scala factory

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实例 - 生产代码中的常见模式来解决问题。)

2 个答案:

答案 0 :(得分:3)

使用apply方法而不是对象作为工厂,详见我的问题How to use companion factory objects as strategy?的答案

答案 1 :(得分:1)

您可能需要查看ScalaMock,这是Scala的模拟框架,可以(除其他外)模拟对象创建(编译器调用)。这正是它要解决的问题之一。