Documentation

You are viewing the documentation for the 2.4.2 release in the 2.4.x series of releases. The latest stable release series is 3.0.x.

§Testing with Guice

If you’re using Guice for dependency injection then you can directly configure how components and applications are created for tests. This includes adding extra bindings or overriding existing bindings.

§GuiceApplicationBuilder

GuiceApplicationBuilder provides a builder API for configuring the dependency injection and creation of an Application.

§Imports

The main imports you’ll need for building applications with Guice are:

import play.Application;
import play.inject.guice.GuiceApplicationBuilder;

§Environment

The Environment, or parts of the environment such as the root path, mode, or class loader for an application, can be specified. The configured environment will be used for loading the application configuration, it will be used when loading modules and passed when deriving bindings from Play modules, and it will be injectable into other components.

Application application = new GuiceApplicationBuilder()
    .in(new Environment(new File("path/to/app"), classLoader, Mode.TEST))
    .build();
Application application = new GuiceApplicationBuilder()
    .in(new File("path/to/app"))
    .in(Mode.TEST)
    .in(classLoader)
    .build();

§Configuration

Additional configuration can be added. This configuration will always be in addition to the configuration loaded automatically for the application. When existing keys are used the new configuration will be preferred.

Configuration extraConfig = new Configuration(ImmutableMap.of("a", 1));
Map<String, Object> configMap = ImmutableMap.of("b", 2, "c", "three");

Application application = new GuiceApplicationBuilder()
    .configure(extraConfig)
    .configure(configMap)
    .configure("key", "value")
    .build();

The automatic loading of configuration from the application environment can also be overridden. This will completely replace the application configuration. For example:

Application application = new GuiceApplicationBuilder()
    .loadConfig(env -> Configuration.load(env))
    .build();

§Bindings and Modules

The bindings used for dependency injection are completely configurable. The builder methods support Play Modules and Bindings and also Guice Modules.

§Additional bindings

Additional bindings, via Play modules, Play bindings, or Guice modules, can be added:

import static play.inject.Bindings.bind;
Application application = new GuiceApplicationBuilder()
    .bindings(new ComponentModule())
    .bindings(bind(Component.class).to(DefaultComponent.class))
    .build();

§Override bindings

Bindings can be overridden using Play bindings, or modules that provide bindings. For example:

Application application = new GuiceApplicationBuilder()
    .overrides(bind(Component.class).to(MockComponent.class))
    .build();

§Disable modules

Any loaded modules can be disabled by class name:

Application application = new GuiceApplicationBuilder()
    .disable(ComponentModule.class)
    .build();

§Loaded modules

Modules are automatically loaded from the classpath based on the play.modules.enabled configuration. This default loading of modules can be overridden. For example:

import play.inject.guice.Guiceable;
Application application = new GuiceApplicationBuilder()
    .load(
        Guiceable.modules(
            new play.api.inject.BuiltinModule(),
            new play.inject.BuiltInModule()
        ),
        Guiceable.bindings(
            bind(Component.class).to(DefaultComponent.class)
        )
    ).build();

§GuiceInjectorBuilder

GuiceInjectorBuilder provides a builder API for configuring Guice dependency injection more generally. This builder does not load configuration or modules automatically from the environment like GuiceApplicationBuilder, but provides a completely clean state for adding configuration and bindings. The common interface for both builders can be found in GuiceBuilder. A Play Injector is created. Here’s an example of instantiating a component using the injector builder:

import play.inject.Injector;
import play.inject.guice.GuiceInjectorBuilder;
import static play.inject.Bindings.bind;
Injector injector = new GuiceInjectorBuilder()
    .configure("key", "value")
    .bindings(new ComponentModule())
    .overrides(bind(Component.class).to(MockComponent.class))
    .injector();

Component component = injector.instanceOf(Component.class);

§Overriding bindings in a functional test

Here is a full example of replacing a component with a mock component for testing. Let’s start with a component, that has a default implementation and a mock implementation for testing:

public interface Component {
    String hello();
}
public class DefaultComponent implements Component {
    public String hello() {
        return "default";
    }
}
public class MockComponent implements Component {
    public String hello() {
        return "mock";
    }
}

This component is loaded automatically using a module:

import com.google.inject.AbstractModule;

public class ComponentModule extends AbstractModule {
    protected void configure() {
        bind(Component.class).to(DefaultComponent.class);
    }
}

And the component is used in a controller:

import play.mvc.*;
import javax.inject.Inject;
import javax.inject.Singleton;

@Singleton
public class Application extends Controller {

    private final Component component;

    @Inject
    public Application(Component component) {
        this.component = component;
    }

    public Result index() {
        return ok(component.hello());
    }

}

To build an Application to use in functional tests we can simply override the binding for the component:

import play.Application;
import play.inject.guice.GuiceApplicationBuilder;
import static play.inject.Bindings.bind;
Application application = new GuiceApplicationBuilder()
    .overrides(bind(Component.class).to(MockComponent.class))
    .build();

This application can be used with test helpers such as running and WithApplication.

Next: Testing with databases