The Play class GuiceApplicationBuilder allows to override the default module binding for specific tests.
Note, that binding overriding with GuiceApplicationBuilder is possible only if dependency injection is done with Guice - the Play default (see Testing with Guice of Play manual).
Overriding dependency injection binding for tests
The post Custom injection binding with Guice in Play shows an example of flexible injection binding with a module method configure.
Injection binding in the example is done like this (the original example code is a bit different):
public class Module extends AbstractModule {
private final Environment environment;
public Module(Environment environment, Configuration configuration) {
this.environment = environment;
}
@Override
protected void configure() {
bind(SessionProvider.class).to(SessionInCashProvider.class);
if (environment.isTest() ) {
bind(CacheProvider.class).to(FakeCacheProvider.class);
}
else {
bind(CacheProvider.class).to(RuntimeCacheProvider.class);
}
}
}
The class SessionInCacheProvider implements an interface SessionProvider and has an injected data member cacheProvider: public class SessionInCacheProvider implements SessionProvider {
@Inject
private CacheProvider cacheProvider;
...
}
The class RuntimeCacheProvider implements the interface CacheProvider for a real application, while FakeCacheProvider is a dummy implementation to be used for tests. The decision, which implementation should be used, is done by the module itself according to the environment.Such method of binding has a serious disadvantage, since it couples between application and tests. Besides, it replaces the binding for all tests globally.
Overriding of injection binding for tests with GuiceApplicationBuilder is the better alternative. The example below shows how this may be done.
1. A module implementation of dependency injection binding is not aware, which binding should be done for tests:
public class Module extends AbstractModule {
private final Environment environment;
public Module(Environment environment, Configuration configuration) {
this.environment = environment;
}
@Override
protected void configure() {
bind(SessionProvider.class).to(SessionInCashProvider.class);
if (!environment.isTest() ) {
bind(CacheProvider.class).to(RuntimeCacheProvider.class);
}
}
}
2. Class FakeApplicationTestBase overrides the default dependency injection binding for the interface CacheProvider: package utils;
import static play.inject.Bindings.bind;
import guiceExamples.cache.CacheProvider;
import play.Application;
import play.Mode;
import play.inject.guice.GuiceApplicationBuilder;
import play.test.WithApplication;
public abstract class FakeApplicationTestBase extends WithApplication {
@Override
protected Application provideApplication() {
return new GuiceApplicationBuilder()
.overrides(bind(CacheProvider.class).to(FakeCacheProvider.class))
.in(Mode.TEST)
.build();
}
protected Injector getInjector() {
return app.injector();
}
}
3. Test class derives from FakeApplicationTestBase. It injects an instance of a sessionProvider with fake application injector: public class TestInCacheSessionProvider extends FakeApplicationTestBase {
static private String FAKE_USER ="FAKE_USER";
static private String FAKE_PASSWORD = "FAKE_PASSWORD";
static private String FAKE_DATA = "FAKE_DATA";
private SessionProvider sessionProvider;
@Before
public void setUp() {
sessionProvider = getInjector().instanceOf(SessionProvider.class);
}
@Test
public void testEncodeDecodeSession() {
SessionDTO sessionId = sessionProvider.startSession(FAKE_USER, FAKE_PASSWORD);
assertNotNull(sessionId);
sessionId.setData(FAKE_DATA);
String sessionEncrypt = sessionProvider.encryptSession(sessionId);
assertFalse(sessionEncrypt.isEmpty());
SessionDTO restoredSessionId = sessionProvider.restoreSession(sessionEncrypt);
assertNotNull(restoredSessionId);
assertEquals(sessionId.getUuid(), restoredSessionId.getUuid());
assertEquals(sessionId.getData(), restoredSessionId.getData());
}
}
Injection with GuiceApplicationBuilder detaches between application and tests. It even allows to define different bindings for different tests - just with another class that extends the WithApplication. Running test with a fakeApplication with different injection binding
The above test testEncodeDecodeSession creates an instance of a sessionProvider by explicit call to the fake application injector.
If a test should be run with a fake application, the proper method for fakeApplication creation should be used. Call to Helpers.running method should be done with provideApplication() instead of Helpers.fakeApplication():
public class TestInCacheSessionProvider extends FakeApplicationTestBase {
import static play.test.Helpers.running;
...
@Test
public void testSomething() {
running(provideApplication(), () -> {
// put test stuff
// put asserts
});
}
}
Call to Helpers.fakeApplication() will create an application with the default injection binding.See on Git working code examples.
No comments :
Post a Comment