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