question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Play tests with mocked Lagom services fails to build Injector

See original GitHub issue

Since 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:open
  • Created 4 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
ignasi35commented, Oct 2, 2019

What about reverting back to just-in-time bindings? My concern is that this workaround is really not going to be obvious to most users.

SGTM, the efforts driving into a non-Guice specific implementation to be more CDI compatible seem stalled.

1reaction
TimMoorecommented, Oct 2, 2019

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:

  1. Provide a test helper for Play apps that use Lagom clients that binds TestServiceLocator, just like the Lagom ServiceTest does.
  2. Revert back to just-in-time (implicit) bindings for JavadslServiceClientImplementor and ServiceClientLoader.
Read more comments on GitHub >

github_iconTop Results From Across the Web

Injector error while running lagom test - Stack Overflow
com.google.inject.CreationException: Unable to create injector, see the following errors: 1) No implementation for com.lightbend.lagom.javadsl.
Read more >
Testing Services - Lagom Framework
Running tests from your IDE will be specific to your IDE, so we'll focus here on how to run tests from sbt. To...
Read more >
lagom/lagom - Gitter
It sounds like that's a closer fit to the problem. ... there isn't an injector is when you build a service client from...
Read more >
Mocking services in a test - Lagom
How do you mock a Service Locator and its dependent Services in tests? Are there any examples? I need it as an alternative...
Read more >
Testing in Lagom(Advanced Testing Scenarios) | by Knoldus Inc.
In order to test a service in Lagom we will basically be starting up a fake server which will make calls to our...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found