/sigmah/src/test/java/org/sigmah/test/InjectionSupport.java
Java | 157 lines | 114 code | 29 blank | 14 comment | 12 complexity | cbc4b7dae96bee1d95b0e6df6b4b216c MD5 | raw file
1/* 2 * All Sigmah code is released under the GNU General Public License v3 3 * See COPYRIGHT.txt and LICENSE.txt. 4 */ 5 6package org.sigmah.test; 7 8import com.google.inject.AbstractModule; 9import com.google.inject.Guice; 10import com.google.inject.Injector; 11import com.google.inject.Module; 12import com.google.inject.name.Names; 13import org.junit.AfterClass; 14import org.junit.internal.runners.statements.RunAfters; 15import org.junit.runner.notification.RunNotifier; 16import org.junit.runners.BlockJUnit4ClassRunner; 17import org.junit.runners.model.FrameworkMethod; 18import org.junit.runners.model.InitializationError; 19import org.junit.runners.model.Statement; 20import org.sigmah.server.dao.OnDataSet; 21import org.sigmah.server.dao.hibernate.LoadDataSet; 22 23import javax.persistence.EntityManagerFactory; 24import java.lang.reflect.Method; 25import java.util.ArrayList; 26import java.util.List; 27 28public class InjectionSupport extends BlockJUnit4ClassRunner { 29 private Injector injector; 30 private TestScopeModule scopeModule; 31 private List<Module> modules; 32 33 public InjectionSupport(Class<?> klass) throws InitializationError { 34 super(klass); 35 36 modules = new ArrayList<Module>(); 37 38 scopeModule = new TestScopeModule(); 39 modules.add(scopeModule); 40 addModulesFromClass(klass); 41 42 System.err.println("Creating injector for " + klass.getName()); 43 injector = Guice.createInjector(modules); 44 } 45 46 private void addModulesFromClass(Class<?> klass) { 47 while (klass != null) { 48 Modules moduleClasses = klass.getAnnotation(Modules.class); 49 if (moduleClasses != null) { 50 addModulesFromAnnotation(klass, moduleClasses); 51 } 52 klass = klass.getSuperclass(); 53 } 54 } 55 56 private void addModulesFromAnnotation(Class<?> klass, Modules moduleClasses) { 57 for (Class moduleClass : moduleClasses.value()) { 58 try { 59 modules.add((Module) moduleClass.getConstructor().newInstance()); 60 } catch (Exception e) { 61 throw new RuntimeException("Exception thrown while creating modules for test " + 62 klass.getName() + ":\n could not instantiate module class " + 63 moduleClass.getName(), e); 64 } 65 } 66 } 67 68 @Override 69 protected void validateConstructor(List<Throwable> errors) { 70 // We'll just have to wait for Guice to throw errors if there is a problem 71 } 72 73 @Override 74 protected Object createTest() throws Exception { 75 scopeModule.getTestScope().enter(); 76 return injector.getInstance(getTestClass().getJavaClass()); 77 } 78 79 @Override 80 protected Statement classBlock(RunNotifier notifier) { 81 Statement statement = super.classBlock(notifier); 82 for (Module module : modules) { 83 statement = withModuleAfterClasses(statement, module); 84 } 85 return statement; 86 } 87 88 @Override 89 protected Statement methodInvoker(FrameworkMethod method, Object test) { 90 Statement statement = super.methodInvoker(method, test); 91 92 statement = withLoadDataSets(method, statement, test); 93 statement = new ExitScope(statement, scopeModule.getTestScope()); 94 return statement; 95 } 96 97 private Statement withLoadDataSets(FrameworkMethod method, Statement statement, Object target) { 98 OnDataSet ods = method.getAnnotation(OnDataSet.class); 99 100 if (ods == null) { 101 ods = target.getClass().getAnnotation(OnDataSet.class); 102 } 103 104 return ods == null ? statement : 105 new LoadDataSet(injector.getInstance(EntityManagerFactory.class), statement, ods.value(), target); 106 } 107 108 /** 109 * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class 110 * and superclasses before executing {@code statement}; all AfterClass methods are 111 * always executed: exceptions thrown by previous steps are combined, if 112 * necessary, with exceptions from AfterClass methods into a 113 * {@link org.junit.internal.runners.model.MultipleFailureException}. 114 */ 115 protected Statement withModuleAfterClasses(Statement statement, Module module) { 116 List<FrameworkMethod> afters = getAnnotatedModuleMethods(module, AfterClass.class); 117 return afters.isEmpty() ? statement : 118 new RunAfters(statement, afters, module); 119 } 120 121 protected List<FrameworkMethod> getAnnotatedModuleMethods(Module module, Class annotationClass) { 122 List<FrameworkMethod> annotated = new ArrayList<FrameworkMethod>(); 123 for (Method method : module.getClass().getMethods()) { 124 if (method.getAnnotation(annotationClass) != null) { 125 annotated.add(new FrameworkMethod(method)); 126 } 127 } 128 return annotated; 129 } 130 131 132 public static class TestScopeModule extends AbstractModule { 133 134 private SimpleScope testScope; 135 136 public TestScopeModule() { 137 } 138 139 @Override 140 protected void configure() { 141 testScope = new SimpleScope(); 142 143 // tell Guice about the scope 144 bindScope(TestScoped.class, testScope); 145 146 // make our scope instance injectable 147 bind(SimpleScope.class) 148 .annotatedWith(Names.named("test")) 149 .toInstance(testScope); 150 } 151 152 public SimpleScope getTestScope() { 153 return testScope; 154 } 155 156 } 157}