/*
* Copyright (c) 2008-2015 Maxifier Ltd. All Rights Reserved.
*/
package com.maxifier.guice.bootstrap;
import com.google.common.collect.Ordering;
import com.google.inject.*;
import com.google.inject.name.Names;
import com.google.inject.spi.DefaultElementVisitor;
import com.google.inject.spi.Element;
import com.google.inject.spi.Elements;
import com.google.inject.util.Types;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import static java.util.Arrays.asList;
/**
* @author Konstantin Lyamshin (2015-11-05 20:06)
*/
public class InjectorBuilderTest extends org.testng.Assert {
InjectorBuilder builder;
@BeforeMethod
public void setUp() throws Exception {
Properties configuration = new Properties();
configuration.load(this.getClass().getResourceAsStream("/config.properties"));
builder = new InjectorBuilder().withConfiguration(configuration);
}
@Test
public void testBuildModule() throws Exception {
Module module = builder
.withModule(new SpecificModule1())
.buildApplicationModule();
boolean found = false;
for (Element element : Elements.getElements(module)) {
found |= element.acceptVisitor(new DefaultElementVisitor<Boolean>() {
@Override
public <T> Boolean visit(Binding<T> binding) {
return binding.getKey().equals(Key.get(Foo.class));
}
});
}
assertEquals(found, true);
}
@Test
public void testBuildInjector() throws Exception {
Injector injector = builder
.withModule(new SpecificModule1())
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
}
@Test(dependsOnMethods = "testBuildInjector")
public void testNoConfig() throws Exception {
Injector injector = new InjectorBuilder()
.withModule(new SpecificModule1())
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
}
@Test(dependsOnMethods = "testBuildInjector")
public void testCustomBundle() throws Exception {
builder.withModuleBundle(bundle("custom", SpecificModule1.class, ConfiguredModule.class));
Injector injector = builder.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
assertEquals(injector.getInstance(List.class).toString(), "[]");
}
@Test(dependsOnMethods = "testCustomBundle", expectedExceptions = IllegalArgumentException.class)
public void testWrongModule() throws Exception {
builder.withModuleBundle(bundle("custom", WrongModule.class));
builder.buildConfigurationInjector();
}
@Test(dependsOnMethods = "testCustomBundle")
public void testConfiguredModule() throws Exception {
builder.withModuleBundle(bundle("custm", SpecificModule1.class));
builder.withModuleBundle(bundle("custom", ConfiguredModule.class));
Injector injector = builder.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Key.get(String.class, Names.named("config"))), "b=[custm],m=[SpecificModule1{}],p=cscfg,c=ijcfg");
}
@Test(dependsOnMethods = "testCustomBundle")
public void testConfiguredProvider() throws Exception {
builder.withModuleBundle(bundle("custp", SpecificModule1.class));
builder.withModuleBundle(bundle("custom", ConfiguredProvider.class));
Injector injector = builder.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Key.get(String.class, Names.named("config"))), "b=[custp],m=[SpecificModule1{}],p=cscfg,c=ijcfg");
}
@Test(dependsOnMethods = "testConfiguredProvider", expectedExceptions = IllegalArgumentException.class)
public void testWrongProvider() throws Exception {
builder.withModuleBundle(bundle("custom", WrongProvider.class));
builder.buildConfigurationInjector();
}
@Test(dependsOnMethods = "testCustomBundle")
public void testStringBundle() throws Exception {
Injector injector = builder
.withModuleBundle("com.maxifier.guice.bootstrap.Bundle.cust")
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
assertEquals(injector.getInstance(List.class).toString(), "[]");
}
@Test(dependsOnMethods = "testCustomBundle")
public void testEnumBundle() throws Exception {
Injector injector = builder
.withModuleBundle(Bundle.cust)
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
assertEquals(injector.getInstance(List.class).toString(), "[]");
}
@Test(dependsOnMethods = "testEnumBundle")
public void testImplements() throws Exception {
Injector injector = builder.withModuleBundle(Bundle.impl).buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "FooImpl{}");
}
@Test(dependsOnMethods = "testEnumBundle")
public void testExtends() throws Exception {
Injector injector = builder.withModuleBundle(Bundle.ext).buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "FooImpl2{}");
}
@Test(dependsOnMethods = "testEnumBundle")
public void testOverrides() throws Exception {
Injector injector = builder.withModuleBundle(Bundle.over).buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "FooImplEx{}");
}
@Test(dependsOnMethods = "testImplements")
public void testModuleDup() throws Exception {
Module module = new ConfiguredModule();
Injector injector = builder
.withModule(module)
.withModule(module)
.withModuleBundle(Bundle.impl)
.withModuleBundle(Bundle.impl)
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImpl{}");
assertEquals(injector.getInstance(List.class).toString(), "[]");
}
@Test(dependsOnMethods = "testNoConfig")
public void testPluginNoConfig() throws Exception {
Injector injector = new InjectorBuilder()
.withModule(new SpecificModule1())
.withPlugin(new PluginModule())
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).name(), "FooImplEx{}");
}
private static File lookupPluginDir() {
URL url = InjectorBuilderTest.class.getResource("/");
assertEquals(url.getProtocol(), "file");
assertTrue(url.getPath().endsWith("/target/test-classes/"));
return new File(url.getPath(), "../../src/test/jars");
}
@Test(dependsOnMethods = "testPluginNoConfig")
public void testCustomPlugin() throws Exception {
Injector injector = builder
.withModuleBundle(Bundle.impl)
.withPluginDir(lookupPluginDir())
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.Plugin1"))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "Foo1{}");
}
@Test(dependsOnMethods = "testNoConfig")
public void testStringPlugin() throws Exception {
Injector injector = builder
.withModuleBundle(Bundle.impl)
.withPluginDir(lookupPluginDir())
.withPluginBundle("com.maxifier.guice.bootstrap.Bundle.plug")
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "Foo1{}");
}
@Test(dependsOnMethods = "testNoConfig")
public void testEnumPlugin() throws Exception {
Injector injector = builder
.withPluginDir(lookupPluginDir())
.withModuleBundle(Bundle.impl)
.withPluginBundle(Bundle.plug)
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "Foo1{}");
}
@Test(dependsOnMethods = "testStringPlugin", expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*not found.*")
public void testWrongPlugin1() throws Exception {
builder
.withPluginDir(lookupPluginDir())
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.MissedPlugin"));
}
@Test(dependsOnMethods = "testStringPlugin", expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*implement Module.*")
public void testWrongPlugin2() throws Exception {
builder
.withPluginDir(lookupPluginDir())
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.PluginWrong"));
}
@Test(dependsOnMethods = "testCustomPlugin")
public void testConfiguredPlugin() throws Exception {
Injector injector = builder
.withPluginDir(lookupPluginDir())
.withModuleBundle(bundle("impl", SpecificModule1.class))
.withPluginBundle(bundle("plugin", ConfiguredModule.class))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Key.get(String.class, Names.named("config"))), "b=[impl],m=[SpecificModule1{}],p=cscfg,c=ijcfg");
}
@Test(dependsOnMethods = "testCustomPlugin")
public void testPluginProvider() throws Exception {
Injector injector = builder
.withPluginDir(lookupPluginDir())
.withModuleBundle(bundle("impl", SpecificModule1.class))
.withPluginBundle(bundle("plugin", ConfiguredProvider.class))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Key.get(String.class, Names.named("config"))), "b=[impl],m=[SpecificModule1{}],p=cscfg,c=ijcfg");
}
@Test(dependsOnMethods = "testCustomPlugin")
public void testPluginDirs() throws Exception {
Injector injector = builder
.withModuleBundle(Bundle.impl)
.withPluginDir(lookupPluginDir(), false)
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.Plugin2"))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "Foo2{}");
}
@Test(dependsOnMethods = "testPluginDirs")
public void testPluginFlatDirs() throws Exception {
Injector injector = builder
.withModuleBundle(Bundle.impl)
.withPluginDir(new File(lookupPluginDir(), "plugin2"), true)
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.Plugin2"))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(CommonService.class).toString(), "Foo2{}");
}
@Test(dependsOnMethods = "testPluginDirs", expectedExceptions = IllegalArgumentException.class)
public void testPluginFlatDirs2() throws Exception {
builder
.withModuleBundle(Bundle.impl)
.withPluginDir(new File(lookupPluginDir(), "plugin2"), true)
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.Plugin1"));
}
@Test(dependsOnMethods = "testCustomPlugin")
public void testClassLoader() throws Exception {
ClassLoader classLoader = new URLClassLoader(new URL[] {}, this.getClass().getClassLoader());
Injector injector = builder
.withClassLoader(classLoader)
.withPluginDir(lookupPluginDir())
.withModuleBundle(Bundle.impl)
.withPluginBundle(bundle("plugin", "com.maxifier.guice.bootstrap.Plugin1"))
.buildApplicationInjector(Stage.DEVELOPMENT);
assertEquals(injector.getInstance(Foo.class).getClass().getClassLoader().getParent(), classLoader);
assertEquals(injector.getInstance(CommonService.class).getClass().getClassLoader(), classLoader.getParent());
}
@Test(dependsOnMethods = "testPluginNoConfig")
public void testMultibinder() throws Exception {
Injector injector = new InjectorBuilder()
.withModule(new Multibinder1())
.withPlugin(new Multibinder2())
.buildApplicationInjector(Stage.DEVELOPMENT);
Object[] set = ((Set<?>) injector.getInstance(Key.get(Types.setOf(Foo.class)))).toArray();
Arrays.sort(set, Ordering.usingToString());
assertEquals(Arrays.toString(set), "[FooImpl2{}, FooImplEx{}]");
}
private static ModuleBundle bundle(final String name, final Class<?>... modules) {
String[] moduleNames = new String[modules.length];
for (int i = 0; i < modules.length; i++) {
moduleNames[i] = modules[i].getName();
}
return bundle(name, moduleNames);
}
private static ModuleBundle bundle(final String name, final String... modules) {
return new ModuleBundle() {
@Override
public String name() {
return name;
}
@Override
public Iterable<String> modules() {
return asList(modules);
}
};
}
}