PageRenderTime 21ms CodeModel.GetById 11ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/sigmah/src/test/java/org/sigmah/test/InjectionSupport.java

http://sigma-h.googlecode.com/
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}