[2.5.10] Testing DI classes

73 views
Skip to first unread message

Igmar Palsenberg

unread,
Dec 19, 2016, 3:50:22 PM12/19/16
to Play Framework

Hi,

I'm upgrading the tests from 2.4 to 2.5, and some things broke. I'm attempting to test an DI class, bound in a Guice module with a @Named annotation.
The Guice module is loaded in the app's application.conf as a play.modules.enabled module. That doesn't seem to be working anymore : The classes don't get binded in Guice.

The test classes' code : 

public class EHCacheCacheTest {
    @Inject
    @EHCache("games")
    Cache cache;

    @Inject
    Application application;

    @Before
    public void init() {
        final Map<String, Object> configuration = new HashMap<>();
        configuration.put("cache.bindCaches", Collections.singletonList("games"));
        configuration.put("cache.games.type", "ehcache");
        configuration.put("play.modules.enabled", Collections.singletonList("com.bm.common.cache.CacheModule"));

        final GuiceApplicationBuilder builder = new GuiceApplicationBuilder().
                load(Guiceable.modules(
                        new play.api.inject.BuiltinModule(),
                        new play.inject.BuiltInModule()
                )).
                configure(configuration);
        Guice.createInjector(builder.applicationModule()).injectMembers(this);
        Helpers.start(application);
        cache.clear();
    }
}

If I leave out the binding of BuiltInModule(), it can't find Play's classes (which makes sense). It now can't find the bindings for @EHCache, which is defined in com.bm.common.cache.CacheModule

Any idea what I'm missing ? I can't load that module itself, since it needs Environment and Configuration, which I don't seem to have.



Igmar


Greg Methvin

unread,
Dec 19, 2016, 5:01:58 PM12/19/16
to play-framework
Hi Igmar,

When you use loadModules() it's defining the entire list of modules Play uses. I'm not sure what type of module CacheModule is, but there is an overloaded version of load() that accepts Play modules and another one that accepts Guice modules: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play-java/src/main/java/play/inject/guice/GuiceApplicationBuilder.java#L97

If you need the Environment and Configuration you can use the version of load that accepts a function: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play-java/src/main/java/play/inject/guice/GuiceApplicationBuilder.java#L75

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/159a738c-1fe5-4d76-8dbc-b7ef587fb09b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Tech Lead - Play Framework

Igmar Palsenberg

unread,
Dec 19, 2016, 5:42:41 PM12/19/16
to Play Framework

HI,
 
When you use loadModules() it's defining the entire list of modules Play uses. I'm not sure what type of module CacheModule is, but there is an overloaded version of load() that accepts Play modules and another one that accepts Guice modules: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play-java/src/main/java/play/inject/guice/GuiceApplicationBuilder.java#L97

We might need to make that a bit more clear in the docs : If you override it, you replace the default bindings Play uses internally.
 
If you need the Environment and Configuration you can use the version of load that accepts a function: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play-java/src/main/java/play/inject/guice/GuiceApplicationBuilder.java#L75

Yeah, I tried that one : It complains play.inject.ApplicationLifecycle isn't bound. I'll do some digging in where that is normally bind()'ed internally.


Igmar 

 

Igmar Palsenberg

unread,
Dec 20, 2016, 1:44:52 AM12/20/16
to Play Framework


Op maandag 19 december 2016 23:42:41 UTC+1 schreef Igmar Palsenberg:
I did a load() for the Play internal bindings, followed by a load for my own module. That didn't work : I needed to call bindings() for the Play internals.
Can someone explain why it's needed this way ?


Igmar

Greg Methvin

unread,
Dec 20, 2016, 3:32:00 AM12/20/16
to play-framework
All of the load() methods essentially replace the module loader for the Play application modules (by replacing the loader function), but not the ones added by bindings(). I guess the documentation has to be a lot more clear about that.

You can also add modules using bindings() and pass Play or Guice modules, or GuiceableModules. If you need Environment and Configuration to create modules in bindings() I think you'd have to implement a GuiceableModule and return the modules from that.

You could also let Play instantiate modules via reflection by setting the play.modules.enabled and/or play.modules.disabled configuration keys. That should work with any module that's normally loadable.

Also, Is there a reason you need to completely replace the default modules? You could just let Play load the modules from the environment (meaning don't call load) and use bindings() to add additional ones.

Greg

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Igmar Palsenberg

unread,
Dec 20, 2016, 9:24:40 AM12/20/16
to Play Framework
Op dinsdag 20 december 2016 09:32:00 UTC+1 schreef Greg Methvin:
All of the load() methods essentially replace the module loader for the Play application modules (by replacing the loader function), but not the ones added by bindings(). I guess the documentation has to be a lot more clear about that.

Yeah, think so.

You can also add modules using bindings() and pass Play or Guice modules, or GuiceableModules. If you need Environment and Configuration to create modules in bindings() I think you'd have to implement a GuiceableModule and return the modules from that.

I used bindings() for the Play internal modules, and load() since I needed Environment and Configuration. That works for me.
 
You could also let Play instantiate modules via reflection by setting the play.modules.enabled and/or play.modules.disabled configuration keys. That should work with any module that's normally loadable.

Also, Is there a reason you need to completely replace the default modules? You could just let Play load the modules from the environment (meaning don't call load) and use bindings() to add additional ones.

Looking at the implementation and trial-and-error usually works. But the docs around DI testing does need some work. Normally, it's find, and I can use the default WithApplication etc handlers, which do the job fine. This part is in a common SBT module, that doesn't have a Play application, and then it doesn't work.
This is a Play Cache replacement that replaces it with proper JSR107 implementation (redis, memcached, ehcache) switchable by annotations.



Igmar 
Reply all
Reply to author
Forward
0 new messages