Play tests with mocked Lagom services fails to build Injector
See original GitHub issueSince Lagom 1.5.0
there’s a new ServiceClientModule
Guice module that service clients will get loaded by default. The ServiceClientModule
was introduced in https://github.com/lagom/lagom/pull/1385/files#diff-32 and indirectly requires a ServiceLocator
.
Play users that inject a Lagom Service.Descriptor
on their code usually mock that on their tests. The problem with the appearance of ServiceClientModule
is that Play tests with mocked Lagom instances now get ServiceClientModule
unnecessarily. On top of that, the tests will probably fail because they lack a ServiceLocator
required by ServiceClientModule
but completely unnecessary for a Play unit test.
The symptoms are a Guice error:
[error] 1) No implementation for com.lightbend.lagom.javadsl.api.ServiceLocator was bound.
[error] while locating com.lightbend.lagom.javadsl.api.ServiceLocator
[error] for the 4th parameter of com.lightbend.lagom.internal.javadsl.client.JavadslServiceClientImplementor.<init>(JavadslServiceClientImplementor.scala:46)
[error] at com.lightbend.lagom.internal.javadsl.client.ServiceClientModule.bindings(ServiceClientModule.scala:15):
[error] Binding(class com.lightbend.lagom.internal.javadsl.client.JavadslServiceClientImplementor to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
[error]
[error] 1 error, took 0.148 sec
[error] at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:543)
[error] at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:159)
[error] at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
[error] at com.google.inject.Guice.createInjector(Guice.java:87)
[error] at com.google.inject.Guice.createInjector(Guice.java:78)
[error] at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:201)
[error] at play.inject.guice.GuiceBuilder.injector(GuiceBuilder.java:211)
[error] at play.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.java:121)
And a workaround is to disable the ServiceClientModule
from the Injector since the Lagom clients are being mocked:
// In MyFrontendControllerTest.java
@Before
public void setup() {
// mock Lagom services
mockCustomersService = mock(CustomersService.class);
mockOrderService = mock(OrderService.class);
application = new GuiceApplicationBuilder()
.overrides(bind(OrderService.class).toInstance(mockOrderService))
.overrides(bind(CustomersService.class).toInstance(mockCustomersService))
.disable(ServiceClientModule.class) // Add this line.
.build();
server = Helpers.testServer(application);
server.start();
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
SGTM, the efforts driving into a non-Guice specific implementation to be more CDI compatible seem stalled.
I debugged this a bit more, and understand what’s happening now. Guice isn’t eagerly instantiating the binding, but it does validate that explicit bindings are injectable when creating the injector. This makes some sense: you generally don’t want things to fail at runtime deep within some request because the DI system hasn’t been wired up properly.
I think the only options would be to:
TestServiceLocator
, just like the LagomServiceTest
does.JavadslServiceClientImplementor
andServiceClientLoader
.