Reputation: 13588
I'm working on a use case where my applications needs a singleton object of trait Table
. I have a implementation TableImpl()
that will be used in development environment. However, I want to be able to switch TableImpl()
with MockTableImpl()
in test environment.
What is the most scala way to do this?
I can use a factory to serve out singletons of TableImpl()
, but how does the factory make the decision of returning a TableImpl()
or MockTableImpl()
?
Upvotes: 0
Views: 251
Reputation: 6172
I would recommend against having a component ask for it's dependencies. Instead, have the creator of the component give it its dependencies (dependency injection or inversion of control). This is an approach that fits much better with idiomatic scala.
Just have dependencies passed as constructor parameters. That way, the class can't be constructed without valid dependencies:
class MyApp (table: Table) {
...
}
class TableImpl() extends Table // singleton
// in production
new MyApp (table = new TableImpl()) // or you can use factory or whatever
// in test (assuming scalatest and scalamock)
new MyApp (table = mock[Table])
Upvotes: 1
Reputation: 7456
trait Table {
def size: Int
}
object TableImpl extends Table { //SINGLETON
def size = Math.abs(-5)*11 //real logic
}
Some application class (it may extends App
trait).
class AppContext(table: Table) {
def run = ()
}
Instantiate App using singleton reference.
new AppContext(TableImpl).run
Or construct application context for test reason.
val mock = mock[Table]
//set mock stuff
new AppContext(mock).run
You are encouraged to use some DI
like Macwire, Guice or Cake pattern. My advise is to always make dependencies explicit - do not use singleton object
name directly in class body, but inject it.
Upvotes: 2