While building a new Playframework app I am trying to use the cake pattern.
My first understanding was to mix custom traits into the controllers and pass those provided by Play as parameter:
trait MyComponents {
def actorSystem: ActorSystemClassic
lazy val service = new MyService(actorSystem)
}
class MyController(
controllerComponents: ControllerComponents,
override val actorSystem: ActorSystemClassic) with MyComponents {
// ...
// Use `service` from MyComponents
}
class MyApp extends BuiltInComponentsFromContext(context) {
val controller = new MyController(
controllerComponents, // <- Provided by BuiltInComponentsFromContext
)
}
That worked fine until I had to test MyController
and tried to mock the service
.
To mock the service
I should be able to work with a stub of MyComponents
that will provide the mock. To provide that stub I have to pass it as constructor parameter.
class MyController(
controllerComponents: ControllerComponents,
myComponents: MyComponents,
override val actorSystem: ActorSystemClassic) {
// ...
// Use `myComponents.service`
}
Of course my controller is more complex than that and he need more than one component to work. My fear is to end with a constructor that will become hardly manageable, with a lot of parameters.
To limit the number of parameters, one idea would be to mix all of the components in one. However I am not able to mix the instance on ControllerComponents
provided by the super class BuiltInComponentsFromContext
with MyComponents
:
class MyController(components: MyComponents with ControllerComponents)
class MyApp extends BuiltInComponentsFromContext(context) {
val controller = new MyController(
new MyComponents with /*instance of controllerComponents provided by BuiltInComponentsFromContext*/
)
}
I do not want to pass the controllerComponents
to MyComponents
because that class provide business services, she don not care about controller components.
Can you help me to implement a real life application with the cake pattern ?