Rob Conaway
Rob Conaway

Reputation: 141

Using Scala companion object as factory by extending a factory trait. Better solution?

Scala companion objects are frequently proposed as object factories. They seem to work well for this in the production code, but what about inserting mock objects for testing? The companion object won't know about the mock object and therefore cannot instantiate it.

I'd like to do something like this:

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)

This won't work because a companion object cannot be extended. I'm forced to create a Factory trait for both companion objects to mixin:

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)

Is there a better way to do this? Creating the factory trait just feels wrong, since that's what the companion object is supposed to be good at. (Keep in mind that the Mock artifacts are only known to the test subsystem, so I can't solve the problem by letting object Foo create a FooMock instance - the common pattern in production code).

Upvotes: 2

Views: 1658

Answers (2)

Paul Butcher
Paul Butcher

Reputation: 10852

You might want to take a look at ScalaMock, a mocking framework for Scala that can (among other things) mock object creation (compiler invocation). This is exactly one of the problems it's intended to solve.

Upvotes: 1

Duncan McGregor
Duncan McGregor

Reputation: 18177

Use the apply method rather than the object as your factory, as detailed in the answers to my question How to use companion factory objects as strategy?

Upvotes: 3

Related Questions