View Javadoc
1   /*
2    * Copyright 2008 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *     
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.openehealth.ipf.platform.camel.core.junit;
17  
18  import java.lang.reflect.Method;
19  
20  import org.junit.runner.notification.RunNotifier;
21  import org.junit.runners.model.InitializationError;
22  import org.springframework.test.annotation.DirtiesContext;
23  import org.springframework.test.context.TestExecutionListener;
24  import org.springframework.test.context.TestExecutionListeners;
25  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
26  import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
27  
28  /**
29   * This test runner dirties a Spring application context after all test methods
30   * of a test class has been run.
31   * This allows test methods to use the same application context but mark it as
32   * dirty to ensure that another test class recreates the application context.
33   * <p><b>
34   * ATTENTION: Using this test runner will slow down overall test execution
35   *            significantly!!! Do not use this runner if you don't really need 
36   *            it. Use {@link SpringJUnit4ClassRunner} instead.
37   * </b><p>
38   * Usage:
39   * <blockquote><code><pre>
40   * &#064;RunWith(DirtySpringContextJUnit4ClassRunner.class)
41   * public class MyTest { ...
42   * </pre></code></blockquote>
43   * For this runner to work it is important the the {@link DirtiesContextTestExecutionListener}
44   * is used. By default this is the case when using this runner. If you specify
45   * the listeners explicitly via the {@link TestExecutionListeners} annotation,
46   * make sure that the {@link DirtiesContextTestExecutionListener} is included. E.g.:
47   * <blockquote><code><pre>
48   * &#064;RunWith(DirtySpringContextJUnit4ClassRunner.class)
49   * &#064;TestExecutionListeners({DirtiesContextTestExecutionListener.class, ...})
50   * public class MyTest { ...
51   * </pre></code></blockquote>
52   * @author Jens Riemschneider
53   */
54  public class DirtySpringContextJUnit4ClassRunner extends SpringJUnit4ClassRunner {
55  
56      /**
57       * Standard constructor
58       * @param clazz
59       *          see {@link SpringJUnit4ClassRunner}
60       * @throws InitializationError
61       *          see {@link SpringJUnit4ClassRunner}
62       * @throws org.junit.runners.model.InitializationError 
63       */
64      public DirtySpringContextJUnit4ClassRunner(Class<?> clazz)
65              throws InitializationError {
66          super(clazz);
67      }
68  
69      @Override
70      public void run(RunNotifier notifier) {
71          super.run(notifier);
72          dirtyContext();
73      }
74  
75      private void dirtyContext() throws AssertionError {
76          ensureDirtyContextListenerIsUsed();
77          
78          // run the standard after test method listeners from the Spring JUnit4
79          // runner on a dummy test method that defines the @DirtiesContext 
80          // annotation. This ensures that the DirtiesContextTestExecutionListener
81          // will be triggered and dirties the application context.
82          for (Method method : getClass().getMethods()) {
83              if (method.isAnnotationPresent(DirtiesContext.class)) {
84                  try {
85                      getTestContextManager().afterTestMethod(this, method, null);
86                  } catch (Exception e) {
87                      throw new AssertionError(e);
88                  }
89              }
90          }
91      }
92      
93      private void ensureDirtyContextListenerIsUsed() {
94          for (TestExecutionListener listener : getTestContextManager().getTestExecutionListeners()) {
95              if (listener instanceof DirtiesContextTestExecutionListener) {
96                  return;
97              }
98          }
99          
100         throw new AssertionError(
101                 "DirtiesContextTestExecutionListener must be added when using DirtySpringContextJUnit4ClassRunner");
102     }
103     
104     @DirtiesContext
105     public void dirtyContextDummy() {        
106         // Does nothing. But ensures that the annotation is interpreted by
107         // afterTestMethod
108     }
109 }