View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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.kuali.rice.krad.test;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.junit.Test;
20  import org.junit.runner.RunWith;
21  import org.kuali.rice.core.api.lifecycle.Lifecycle;
22  import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader;
23  import org.kuali.rice.krad.datadictionary.DataDictionary;
24  import org.kuali.rice.krad.util.LegacyUtils;
25  import org.kuali.rice.test.BaselineTestCase;
26  import org.kuali.rice.test.SQLDataLoader;
27  import org.kuali.rice.test.TestUtilities;
28  import org.kuali.rice.test.lifecycles.KEWXmlDataLoaderLifecycle;
29  import org.kuali.rice.test.runners.BootstrapTest;
30  import org.kuali.rice.test.runners.LoadTimeWeavableTestRunner;
31  import org.springframework.context.ConfigurableApplicationContext;
32  import org.springframework.context.support.ClassPathXmlApplicationContext;
33  
34  import javax.xml.namespace.QName;
35  import java.lang.annotation.Retention;
36  import java.lang.annotation.Target;
37  import java.util.ArrayList;
38  import java.util.HashSet;
39  import java.util.List;
40  
41  import static java.lang.annotation.ElementType.METHOD;
42  import static java.lang.annotation.ElementType.TYPE;
43  import static java.lang.annotation.RetentionPolicy.RUNTIME;
44  
45  /**
46   * Default test base for a full KRAD enabled integration test
47   *
48   * @author Kuali Rice Team (rice.collab@kuali.org)
49   */
50  @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK_CLEAR_DB)
51  @RunWith(LoadTimeWeavableTestRunner.class)
52  @BootstrapTest(KRADTestCase.BootstrapTest.class)
53  public abstract class KRADTestCase extends BaselineTestCase {
54      private static final String SQL_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.sql";
55      private static final String XML_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.xml";
56      private static final String KRAD_MODULE_NAME = "krad";
57  
58      protected DataDictionary dd;
59  
60      protected static SpringResourceLoader kradTestHarnessSpringResourceLoader;
61  
62      private boolean legacyContext = false;
63  
64      public KRADTestCase() {
65          super(KRAD_MODULE_NAME);
66      }
67  
68      /**
69       * propagate constructor
70       * @param moduleName - the name of the module
71       */
72      public KRADTestCase(String moduleName) {
73          super(moduleName);
74      }
75  
76      protected ConfigurableApplicationContext getKRADTestHarnessContext() {
77          return kradTestHarnessSpringResourceLoader.getContext();
78      }
79  
80      @Override
81      public void setUp() throws Exception {
82          super.setUp();
83          setUpLegacyContext();
84  
85      }
86  
87      @Override
88      public void tearDown() throws Exception {
89          try {
90              tearDownLegacyContext();
91          } finally {
92              super.tearDown();    //To change body of overridden methods use File | Settings | File Templates.
93          }
94      }
95  
96      protected void setUpLegacyContext() {
97          if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) {
98              LegacyUtils.beginLegacyContext();
99              legacyContext = true;
100         }
101     }
102 
103     protected void tearDownLegacyContext() {
104         if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) {
105             if (legacyContext) {
106                 LegacyUtils.endLegacyContext();
107                 legacyContext = false;
108             }
109         }
110     }
111 
112     @Override
113     protected void setUpInternal() throws Exception {
114         super.setUpInternal();
115 
116         List<Class> classes = TestUtilities.getHierarchyClassesToHandle(getClass(),
117                 new Class[]{TestDictionaryConfig.class}, new HashSet<String>());
118 
119         // if annotation is present then initialize test data dictionary (setup once per suite)
120         if (!classes.isEmpty()) {
121             ConfigurableApplicationContext context  = new ClassPathXmlApplicationContext("TestDataDictionary.xml");
122             dd = (DataDictionary) context.getBean("testDataDictionary");
123 
124             // add any additional dictionary files required by the test
125             for (Class c : classes) {
126                 if (c.isAnnotationPresent(TestDictionaryConfig.class)) {
127                     TestDictionaryConfig testDictionaryConfig = (TestDictionaryConfig) c.getAnnotation(
128                             TestDictionaryConfig.class);
129 
130                     String namespaceCode = testDictionaryConfig.namespaceCode();
131                     String dictionaryFileString = testDictionaryConfig.dataDictionaryFiles();
132 
133                     String[] dictionaryFiles = StringUtils.split(dictionaryFileString, ",");
134                     for (String dictionaryFile : dictionaryFiles) {
135                         LOG.info("Adding test data dictionary file: " + dictionaryFile);
136 
137                         dd.addConfigFileLocation(namespaceCode, dictionaryFile);
138                     }
139                 }
140             }
141 
142             dd.parseDataDictionaryConfigurationFiles(false);
143             dd.validateDD(false); // Validation performs some necessary post-processing of the beans - we need to run this each time we add new files
144             dd.performBeanOverrides();
145         }
146     }
147 
148     /**
149      * Returns an instance of the bean with the given id that has been configured in the test dictionary
150      *
151      * @param id - id of the bean definition
152      * @return Object instance of the given bean class, or null if not found or dictionary is not loaded
153      */
154     protected Object getTestDictionaryObject(String id) {
155         if (dd != null) {
156             return dd.getDictionaryBean(id);
157         }
158 
159         return null;
160     }
161 
162     @Override
163     protected List<Lifecycle> getSuiteLifecycles() {
164         List<Lifecycle> suiteLifecycles = super.getSuiteLifecycles();
165         suiteLifecycles.add(new KEWXmlDataLoaderLifecycle(XML_FILE));
166 
167         return suiteLifecycles;
168     }
169 
170     @Override
171     protected List<String> getPerTestTablesNotToClear() {
172         List<String> tablesNotToClear = new ArrayList<String>();
173         tablesNotToClear.add("KRIM_.*");
174         tablesNotToClear.add("KRCR_.*");
175         tablesNotToClear.add("KREW_.*");
176         return tablesNotToClear;
177     }
178 
179     @Override
180     protected void loadSuiteTestData() throws Exception {
181         super.loadSuiteTestData();
182         new SQLDataLoader(SQL_FILE, ";").runSql();
183     }
184 
185     @Override
186     protected Lifecycle getLoadApplicationLifecycle() {
187         // cache the KRAD test harness spring resource loader
188         // this is not great because it doesn't conform to the lifecycle
189         // ...but why are we creating sub-resourceloaders instead of just adding locations to the test harness context?
190         if (kradTestHarnessSpringResourceLoader == null) {
191             kradTestHarnessSpringResourceLoader = new SpringResourceLoader(new QName("KRADTestResourceLoader"),
192                     "classpath:KRADTestHarnessSpringBeans.xml", null);
193             kradTestHarnessSpringResourceLoader.setParentSpringResourceLoader(getTestHarnessSpringResourceLoader());
194         }
195         return kradTestHarnessSpringResourceLoader;
196     }
197 
198     /**
199      * Annotation which indicates that a Legacy Context should be used for this individual test method or for all tests
200      * in an annotated class.
201      *
202      * @see org.kuali.rice.krad.util.LegacyUtils#doInLegacyContext(java.util.concurrent.Callable)
203      */
204     @Target({TYPE, METHOD})
205     @Retention(RUNTIME)
206     public @interface Legacy {}
207 
208     public static final class BootstrapTest extends KRADTestCase {
209         @Test
210         public void bootstrapTest() {};
211     }
212 
213 }