001/** 002 * Copyright 2005-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.test; 017 018import org.apache.commons.lang.StringUtils; 019import org.junit.Test; 020import org.junit.runner.RunWith; 021import org.kuali.rice.core.api.lifecycle.Lifecycle; 022import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader; 023import org.kuali.rice.krad.datadictionary.DataDictionary; 024import org.kuali.rice.krad.util.LegacyUtils; 025import org.kuali.rice.test.BaselineTestCase; 026import org.kuali.rice.test.SQLDataLoader; 027import org.kuali.rice.test.TestUtilities; 028import org.kuali.rice.test.lifecycles.KEWXmlDataLoaderLifecycle; 029import org.kuali.rice.test.runners.BootstrapTest; 030import org.kuali.rice.test.runners.LoadTimeWeavableTestRunner; 031import org.springframework.context.ConfigurableApplicationContext; 032import org.springframework.context.support.ClassPathXmlApplicationContext; 033 034import javax.xml.namespace.QName; 035import java.lang.annotation.Retention; 036import java.lang.annotation.Target; 037import java.util.ArrayList; 038import java.util.HashSet; 039import java.util.List; 040 041import static java.lang.annotation.ElementType.METHOD; 042import static java.lang.annotation.ElementType.TYPE; 043import static java.lang.annotation.RetentionPolicy.RUNTIME; 044 045/** 046 * Default test base for a full KRAD enabled integration test 047 * 048 * @author Kuali Rice Team (rice.collab@kuali.org) 049 */ 050@BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK_CLEAR_DB) 051@RunWith(LoadTimeWeavableTestRunner.class) 052@BootstrapTest(KRADTestCase.BootstrapTest.class) 053public abstract class KRADTestCase extends BaselineTestCase { 054 private static final String SQL_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.sql"; 055 private static final String XML_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.xml"; 056 private static final String KRAD_MODULE_NAME = "krad"; 057 058 protected DataDictionary dd; 059 060 protected static SpringResourceLoader kradTestHarnessSpringResourceLoader; 061 062 private boolean legacyContext = false; 063 064 public KRADTestCase() { 065 super(KRAD_MODULE_NAME); 066 } 067 068 /** 069 * propagate constructor 070 * @param moduleName - the name of the module 071 */ 072 public KRADTestCase(String moduleName) { 073 super(moduleName); 074 } 075 076 protected ConfigurableApplicationContext getKRADTestHarnessContext() { 077 return kradTestHarnessSpringResourceLoader.getContext(); 078 } 079 080 @Override 081 public void setUp() throws Exception { 082 super.setUp(); 083 setUpLegacyContext(); 084 085 } 086 087 @Override 088 public void tearDown() throws Exception { 089 try { 090 tearDownLegacyContext(); 091 } finally { 092 super.tearDown(); //To change body of overridden methods use File | Settings | File Templates. 093 } 094 } 095 096 protected void setUpLegacyContext() { 097 if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) { 098 LegacyUtils.beginLegacyContext(); 099 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}