Closed Dasiu closed 6 years ago
@Dasiu It seems like you're actually talking about https://github.com/playframework/scalatestplus-play, rather than playframework itself. The core issue I believe is that you want something like components
to access at the class level, but you want to make sure that you're using the same exact instance used by the running application.
The first solution you mentioned seems like an ugly hack. If you're using compile-time DI, ideally you want to access the components in a type-safe way. The best way to do that is directly using the actual components class you used to create the application. Yes, it would be possible to implement an injector that inspects the components class at runtime and calls the right method, but there's no good reason to add another level of indirection.
As far as I can tell this is not a bug in Play at all so I'm closing this, but I opened https://github.com/playframework/scalatestplus-play/issues/108 in scalatestplus-play that I think explains the main problem you're describing. That also describes an idempotent way to access the components for the running application.
API: Scala, Play: 2.6.X
My need is to write functional test, which refers to application component with compile time DI and with server and whole application running. After reading docs, I'm not sure what is proper way to achieve that. I've learned, that I should use injector in order to access application components (including business components) like this:
https://www.playframework.com/documentation/2.6.x/ScalaFunctionalTestingWithScalaTest
Intuitively, I presumed, that for compile time DI it can be done in the same way, of course, without additional magic, programmer needs to set up such injector himself - explicitly. My attempt to do that failed, because
BuiltInComponents.injector
is lazy and following line do not compile:override val injector = new SimpleInjector(super.injector) + ??? /* additional components */
with error: "super may not be used on lazy value injector". Call to super is needed, since
BuiltInComponents
contains some basic dependencies, which are probably needed by an application.After facing that I fell back to another solution. Underneath playframework's test utilities initializes app variable for each test. The variable is initialized based on
WithApplicationComponents.components
definition.components
def is also available in test's body, so my idea was to call it in order to access components required by test, like here:it actually works but it looks like fragile thing, because
components
is a definition, so each call creates differentBuiltInComponentsFromContext
- different to create application for test and different to access application component.Given all that, my questions are:
BuiltInComponentsFromContext
be confined to each test in similar fashion like with aforementionedapp
variable? For me each call tocomponents
is like creating another test box and I want to have only one.My current test infrastructure is a little bit more complicated, it can be found here, if needed: https://github.com/Dasiu/realworld-starter-kit/tree/master/test