Here's the problem I'm facing:
I have an abstract trait Toggles
which has an abstract method isToggleEnabled(name: String)
.
What I want to have is to be able to have production environment trait ProdToggles
with concrete implementation of isToggleEnabled
and use it in the prod code but be able to provide overriding alternate trait TestToggles
with new implementation isToggleEnabled
when testing.
The reason is that production environment implementation uses System properties to store toggle names and their states, however in testing I would like to provide different implementation to store and read toggles, so that multiple tests could be run in parallel without affecting each other (as through System properties they would). What I came up with using cake pattern:
trait Toggleable {
def isToggleEnabled(name: String): Boolean
}
trait ProdToggles extends Toggles with Toggleable {
override def isToggleEnabled(name: String): Boolean = System.getProperty("name").toBoolean
}
trait TestToggles extends Toggles with Toggleable {
val cache = scala.collection.mutable.HashMap.empty[String, Boolean]
override def isToggleEnabled(name: String): Boolean = cache.getOrElse(name, false)
}
trait Toggles {
this: Toggleable =>
def isEnabled(name: String): Boolean = {
isToggleEnabled(name)
}
}
//—————IN PROD code—————
class Prod() {
this: Toggles =>
def doSomething(): Unit ={
isEnabled("toggle.name")
}
}
object Prod {
def apply(): Prod = new Prod with ProdToggles
def apply(testing: Boolean) = new Prod with TestToggles
}
//——————IN TEST code———————————
class Tests {
val prod = Prod(true)
prod.doSomething()
}
However, problem with that:
- Breaks encapsulation and
Prod
instance could be misused asToggle
instance as you could do(new Prod with ProdToggles).{isEnabled, isToggleEnabled, doSomething}
- Every
Prod
class mixinToggles
will need anobject
withapply
constructors to return custom instance for testing and for prod - Cake-pattern is an anti-pattern
Would you have any other approaches to go around this problem? Thanks!
Aucun commentaire:
Enregistrer un commentaire