001 /** 002 * Copyright 2005-2013 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 */ 016 package org.kuali.rice.krad.test; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.junit.Test; 020 import org.junit.runner.RunWith; 021 import org.kuali.rice.core.api.lifecycle.Lifecycle; 022 import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader; 023 import org.kuali.rice.krad.datadictionary.DataDictionary; 024 import org.kuali.rice.krad.util.LegacyUtils; 025 import org.kuali.rice.test.BaselineTestCase; 026 import org.kuali.rice.test.SQLDataLoader; 027 import org.kuali.rice.test.TestUtilities; 028 import org.kuali.rice.test.lifecycles.KEWXmlDataLoaderLifecycle; 029 import org.kuali.rice.test.runners.BootstrapTest; 030 import org.kuali.rice.test.runners.LoadTimeWeavableTestRunner; 031 import org.springframework.context.ConfigurableApplicationContext; 032 import org.springframework.context.support.ClassPathXmlApplicationContext; 033 034 import javax.xml.namespace.QName; 035 import java.lang.annotation.Retention; 036 import java.lang.annotation.Target; 037 import java.util.HashSet; 038 import java.util.List; 039 040 import static java.lang.annotation.ElementType.METHOD; 041 import static java.lang.annotation.ElementType.TYPE; 042 import static java.lang.annotation.RetentionPolicy.RUNTIME; 043 044 /** 045 * Default test base for a full KRAD enabled integration test 046 * 047 * @author Kuali Rice Team (rice.collab@kuali.org) 048 */ 049 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK_CLEAR_DB) 050 @RunWith(LoadTimeWeavableTestRunner.class) 051 @BootstrapTest(KRADTestCase.BootstrapTest.class) 052 public abstract class KRADTestCase extends BaselineTestCase { 053 private static final String SQL_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.sql"; 054 private static final String XML_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.xml"; 055 private static final String KRAD_MODULE_NAME = "krad"; 056 057 protected DataDictionary dd; 058 059 protected static SpringResourceLoader kradTestHarnessSpringResourceLoader; 060 061 private boolean legacyContext = false; 062 063 public KRADTestCase() { 064 super(KRAD_MODULE_NAME); 065 } 066 067 /** 068 * propagate constructor 069 * @param moduleName - the name of the module 070 */ 071 public KRADTestCase(String moduleName) { 072 super(moduleName); 073 } 074 075 protected ConfigurableApplicationContext getKRADTestHarnessContext() { 076 return kradTestHarnessSpringResourceLoader.getContext(); 077 } 078 079 @Override 080 public void setUp() throws Exception { 081 super.setUp(); 082 setUpLegacyContext(); 083 084 } 085 086 @Override 087 public void tearDown() throws Exception { 088 try { 089 tearDownLegacyContext(); 090 } finally { 091 super.tearDown(); //To change body of overridden methods use File | Settings | File Templates. 092 } 093 } 094 095 protected void setUpLegacyContext() { 096 if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) { 097 LegacyUtils.beginLegacyContext(); 098 legacyContext = true; 099 } 100 } 101 102 protected void tearDownLegacyContext() { 103 if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) { 104 if (legacyContext) { 105 LegacyUtils.endLegacyContext(); 106 legacyContext = false; 107 } 108 } 109 } 110 111 @Override 112 protected void setUpInternal() throws Exception { 113 super.setUpInternal(); 114 115 List<Class> classes = TestUtilities.getHierarchyClassesToHandle(getClass(), 116 new Class[]{TestDictionaryConfig.class}, new HashSet<String>()); 117 118 // if annotation is present then initialize test data dictionary (setup once per suite) 119 if (!classes.isEmpty()) { 120 ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("TestDataDictionary.xml"); 121 dd = (DataDictionary) context.getBean("testDataDictionary"); 122 123 // add any additional dictionary files required by the test 124 for (Class c : classes) { 125 if (c.isAnnotationPresent(TestDictionaryConfig.class)) { 126 TestDictionaryConfig testDictionaryConfig = (TestDictionaryConfig) c.getAnnotation( 127 TestDictionaryConfig.class); 128 129 String namespaceCode = testDictionaryConfig.namespaceCode(); 130 String dictionaryFileString = testDictionaryConfig.dataDictionaryFiles(); 131 132 String[] dictionaryFiles = StringUtils.split(dictionaryFileString, ","); 133 for (String dictionaryFile : dictionaryFiles) { 134 LOG.info("Adding test data dictionary file: " + dictionaryFile); 135 136 dd.addConfigFileLocation(namespaceCode, dictionaryFile); 137 } 138 } 139 } 140 141 dd.parseDataDictionaryConfigurationFiles(false); 142 dd.validateDD(false); // Validation performs some necessary post-processing of the beans - we need to run this each time we add new files 143 dd.performBeanOverrides(); 144 } 145 } 146 147 /** 148 * Returns an instance of the bean with the given id that has been configured in the test dictionary 149 * 150 * @param id - id of the bean definition 151 * @return Object instance of the given bean class, or null if not found or dictionary is not loaded 152 */ 153 protected Object getTestDictionaryObject(String id) { 154 if (dd != null) { 155 return dd.getDictionaryObject(id); 156 } 157 158 return null; 159 } 160 161 @Override 162 protected List<Lifecycle> getSuiteLifecycles() { 163 List<Lifecycle> suiteLifecycles = super.getSuiteLifecycles(); 164 suiteLifecycles.add(new KEWXmlDataLoaderLifecycle(XML_FILE)); 165 166 return suiteLifecycles; 167 } 168 169 @Override 170 protected void loadSuiteTestData() throws Exception { 171 super.loadSuiteTestData(); 172 new SQLDataLoader(SQL_FILE, ";").runSql(); 173 } 174 175 @Override 176 protected Lifecycle getLoadApplicationLifecycle() { 177 // cache the KRAD test harness spring resource loader 178 // this is not great because it doesn't conform to the lifecycle 179 // ...but why are we creating sub-resourceloaders instead of just adding locations to the test harness context? 180 if (kradTestHarnessSpringResourceLoader == null) { 181 kradTestHarnessSpringResourceLoader = new SpringResourceLoader(new QName("KRADTestResourceLoader"), 182 "classpath:KRADTestHarnessSpringBeans.xml", null); 183 kradTestHarnessSpringResourceLoader.setParentSpringResourceLoader(getTestHarnessSpringResourceLoader()); 184 } 185 return kradTestHarnessSpringResourceLoader; 186 } 187 188 /** 189 * Annotation which indicates that a Legacy Context should be used for this individual test method or for all tests 190 * in an annotated class. 191 * 192 * @see org.kuali.rice.krad.util.LegacyUtils#doInLegacyContext(java.util.concurrent.Callable) 193 */ 194 @Target({TYPE, METHOD}) 195 @Retention(RUNTIME) 196 public @interface Legacy {} 197 198 public static final class BootstrapTest extends KRADTestCase { 199 @Test 200 public void bootstrapTest() {}; 201 } 202 203 }