package io.bootique.test.junit; import com.google.inject.Module; import io.bootique.BQCoreModule; import io.bootique.BQModuleOverrideBuilder; import io.bootique.BQModuleProvider; import io.bootique.Bootique; import io.bootique.log.BootLogger; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; /** * @since 0.20 */ // parameterization is needed to enable covariant return types in subclasses public abstract class BQTestRuntimeBuilder<T extends BQTestRuntimeBuilder<T>> { protected Bootique bootique; protected Map<String, String> properties; protected BQTestRuntimeBuilder(String[] args) { this.properties = new HashMap<>(); this.bootique = Bootique.app(args).module(createPropertiesProvider()); } protected BQModuleProvider createPropertiesProvider() { return new BQModuleProvider() { @Override public Module module() { return binder -> BQCoreModule.extend(binder).setProperties(properties); } @Override public String name() { return "BQTestRuntimeBuilder:properties"; } }; } /** * Appends extra values to the test CLI arguments. * * @param args extra args to pass to Bootique. * @return this instance of test runtime builder. */ public T args(String... args) { bootique.args(args); return (T) this; } /** * Appends extra values to the test CLI arguments. * * @param args extra args to pass to Bootique. * @return this instance of test runtime builder. */ public T args(Collection<String> args) { bootique.args(args); return (T) this; } /** * Instructs Bootique to load any modules available on classpath that expose {@link io.bootique.BQModuleProvider} * provider. Auto-loaded modules will be used in default configuration. Factories within modules will of course be * configured dynamically from YAML. * * @return this instance of test runtime builder. */ public T autoLoadModules() { bootique.autoLoadModules(); return (T) this; } /** * @param bootLogger custom BootLogger to use for a given runtime. * @return this instance of test runtime builder. * @since 0.23 */ public T bootLogger(BootLogger bootLogger) { bootique.bootLogger(bootLogger); return (T) this; } /** * @param moduleType custom Module class to add to Bootique DI runtime. * @return this instance of test runtime builder. * @see #autoLoadModules() */ public T module(Class<? extends Module> moduleType) { bootique.module(moduleType); return (T) this; } /** * Adds an array of Module types to the Bootique DI runtime. Each type will * be instantiated by Bootique and added to the Guice DI container. * * @param moduleTypes custom Module classes to add to Bootique DI runtime. * @return this instance of test runtime builder. * @see #autoLoadModules() */ public T modules(Class<? extends Module>... moduleTypes) { bootique.modules(moduleTypes); return (T) this; } /** * @param m a module to add to the test runtime. * @return this instance of test runtime builder. */ public T module(Module m) { bootique.module(m); return (T) this; } /** * Adds an array of Modules to the Bootique DI runtime. * * @param modules an array of modules to add to Bootiqie DI runtime. * @return this instance of test runtime builder. */ public T modules(Module... modules) { bootique.modules(modules); return (T) this; } /** * Adds a Module generated by the provider. Provider may optionally specify * that the Module overrides services in some other Module. * * @param moduleProvider a provider of Module and override spec. * @return this instance of test runtime builder. */ public T module(BQModuleProvider moduleProvider) { bootique.module(moduleProvider); return (T) this; } /** * Starts an API call chain to override an array of Modules. * * @param overriddenTypes an array of modules whose bindings should be overridden. * @return {@link BQModuleOverrideBuilder} object to specify a Module * overriding other modules. */ public BQModuleOverrideBuilder<T> override(Class<? extends Module>... overriddenTypes) { BQModuleOverrideBuilder<Bootique> subBuilder = bootique.override(overriddenTypes); return new BQModuleOverrideBuilder<T>() { @Override public T with(Class<? extends Module> moduleType) { subBuilder.with(moduleType); return (T) BQTestRuntimeBuilder.this; } @Override public T with(Module module) { subBuilder.with(module); return (T) BQTestRuntimeBuilder.this; } }; } public T property(String key, String value) { properties.put(key, value); return (T) this; } /** * @param configurator a callback function that configures Bootique stack. * @return this builder instance. * @deprecated since 0.20 use builder methods directly instead of configurator function to add modules, etc. */ @Deprecated public T configurator(Consumer<Bootique> configurator) { Objects.requireNonNull(configurator).accept(bootique); return (T) this; } }