0

I am using Play framework 2.4 and have created a custom wrapper class around a redis hash using the play-redis plugin.

I have an interface:

@ImplementedBy(RedisStoreProvider.class)
public interface IStoreProvider {
    long countStore(String storeKey);
}

And its implementation:

public class RedisStoreProvider implements IStoreProvider {

    @Inject JedisPool jedisPool;

    public long countStore(String storeKey) {
        Jedis j = jedisPool.getResource();
        try {
            return j.hlen(storeKey);
        } finally {
            jedisPool.returnResource(j);
        }
    }
}

When I inject the IStoreProvider into a controller it displays fine:

public class Application extends Controller {
    @Inject IStoreProvider sp;
    public Result index() {
        return ok(index.render("Store card: " + sp.countStore("foo")));
    }
}

Displays "Store card: 0" (as the redis hash is empty)

Yet when I am trying to test this, the JedisPool is null. I am using the following to test:

public class RedisStoreProviderTest {

    @Inject IStoreProvider stProv;

    @Test
    public void cardStoreTest(){
       running(fakeApplication(), () -> {
            assertEquals("Expected 0", 0, stProv.cardStore("foo"));
       }); 
    } 
}

I have tried both with/without the fakeApplication, and both injecting and instantiating the IStoreProvider in the test.

Does Play DI require a injected variable to be in a controller? How can I have unit-tests for classes that require DI?

RichyHBM
  • 798
  • 1
  • 7
  • 18
  • where does `running(fakeApplication()` come from? – zapl Oct 17 '15 at 16:46
  • @zapl Its part of Play, I thought I might have needed to be running the tests within the context of an application for the di to register, but it doesnt seem so. https://www.playframework.com/documentation/2.4.x/JavaFunctionalTest#Testing-with-an-application – RichyHBM Oct 17 '15 at 17:33
  • You usually don't need to run with the full app context, you'll often don't test with DI but manually creating instances under test. Or you create a special stripped down / mocked module like in the example at the bottom: http://www.journaldev.com/2403/google-guice-dependency-injection-example-tutorial (although you don't need to null the injector and I'd setup the dependencies directly in `setUp`, not in the test method). Ps why I was asking: your example test code does not look like that would compile and it's not clear to me where / how those methods are defined. – zapl Oct 17 '15 at 17:53
  • @zapl I tried using that example, or one from the same blog, and I got further than I have done before. It will get to trying to construct a JedisPool but then complains as JedisPoolProvider doesnt have the correct constructor. I am assuming the other required arguments get injected when it is part of a full play application? https://github.com/typesafehub/play-plugins/blob/master/redis/src/main/scala/com/typesafe/play/redis/JedisPoolProvider.scala Regarding my sample code, I missed out the imports. It was more of a quick example code as my full code is much larger. – RichyHBM Oct 17 '15 at 18:41
  • Yes, play will have setup for the other parts. But https://www.playframework.com/documentation/2.4.x/JavaFunctionalTest#Injecting-tests specifically the injector made from the guice builder should be able to do that for you. – zapl Oct 17 '15 at 19:11

0 Answers0