Java tutorial
/* * Copyright 2011-2016 ZXC.com All right reserved. This software is the confidential and proprietary information of * ZXC.com ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into with ZXC.com. */ package com.ms.commons.test; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import junit.framework.TestCase; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import org.springframework.test.AbstractTransactionalSpringContextTests; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import com.ms.commons.core.CommonServiceLocator; import com.ms.commons.test.annotation.Mock; import com.ms.commons.test.annotation.PrepareAnnotationTool; import com.ms.commons.test.annotation.SecondaryJdbcSetting; import com.ms.commons.test.annotation.TestCaseInfo; import com.ms.commons.test.assertion.Assert; import com.ms.commons.test.assertion.exception.AssertException; import com.ms.commons.test.assertion.impl.DataBaseAssertion; import com.ms.commons.test.assertion.impl.ForEachAssertion; import com.ms.commons.test.assertion.impl.JavaBeanAssertion; import com.ms.commons.test.assertion.impl.ParameterizedAssertion; import com.ms.commons.test.cache.BuiltInCacheKey; import com.ms.commons.test.cache.ThreadContextCache; import com.ms.commons.test.common.ExceptionUtil; import com.ms.commons.test.common.ReflectUtil; import com.ms.commons.test.common.SortUtil; import com.ms.commons.test.common.StringUtil; import com.ms.commons.test.common.comparator.Comparator; import com.ms.commons.test.common.dbencoding.DbEncodingUtil; import com.ms.commons.test.common.dbencoding.impl.info.CnStringDbEncodingInfo; import com.ms.commons.test.common.dbencoding.impl.info.UTF8StringDbEncodingInfo; import com.ms.commons.test.common.task.Task; import com.ms.commons.test.common.task.TaskUtil; import com.ms.commons.test.constants.IntlTestGlobalConstants; import com.ms.commons.test.context.TestCaseRuntimeInfo; import com.ms.commons.test.database.JdbcManagementTool; import com.ms.commons.test.database.JdbcManagementToolBuilder; import com.ms.commons.test.database.SecondaryPreareFilter; import com.ms.commons.test.database.SecondarySetting; import com.ms.commons.test.datareader.DataReaderType; import com.ms.commons.test.datareader.DataReaderUtil; import com.ms.commons.test.datareader.exception.ResourceNotFoundException; import com.ms.commons.test.datareader.impl.BaseReaderUtil; import com.ms.commons.test.integration.junit4.internal.IntlTestBlockJUnit4ClassRunner; import com.ms.commons.test.memorydb.MemoryDatabase; import com.ms.commons.test.mock.AliMock; import com.ms.commons.test.mock.MockBeanPostProcessor; import com.ms.commons.test.mock.inject.proxy.ProxyDepackageUtil; import com.ms.commons.test.prepare.PrepareUtil; import com.ms.commons.test.prepare.event.PrepareEventUtil; import com.ms.commons.test.prepare.event.impl.ClearSpecialDataPrepareEvent; import com.ms.commons.test.prepare.impl.DataBasePreparation; import com.ms.commons.test.prepare.impl.ForEachPreparation; import com.ms.commons.test.prepare.impl.JavaBeanPreparation; import com.ms.commons.test.prepare.impl.YamlPreparation; import com.ms.commons.test.treedb.JsonObjectUtils; import com.ms.commons.test.treedb.TreeDatabase; import com.ms.commons.test.treedb.TreeObject; import com.ms.commons.test.treedb.TreeObjectAssert; /** * @author zxc Apr 13, 2013 10:56:47 PM */ @RunWith(IntlTestBlockJUnit4ClassRunner.class) public abstract class BaseTestCase extends AbstractBaseTestCase { protected final Logger log = Logger.getLogger(getClass()); protected static final String DEFAULT_CLASS_SUFFIX = "Data"; protected static final String TESTCASE_BASE_PATH = "testcase.base.path"; protected static volatile boolean firstTimeRan = false; protected static volatile Map<List<Object>, Object> objectMethodMap = new HashMap<List<Object>, Object>(); static { long BEGIN_TIME = System.currentTimeMillis(); Locale.setDefault(Locale.ENGLISH); System.setProperty("ark.trace.sql.stack", "false"); System.setProperty("ark.trace.sql", "SUDI"); // System.setProperty("com.ms.ark.trace.TraceHandler", "com.ms.ark.trace.LoggingTraceHandler"); System.err.println("TEST STATIC INIT TIME " + (System.currentTimeMillis() - BEGIN_TIME)); } protected JdbcManagementTool jdbcManagementTool = null; public BaseTestCase() { System.setProperty(TESTCASE_BASE_PATH, getAbstractBasePath()); } protected Object getService(String name) { return applicationContext.getBean(name); } /** * Spring?IDServiceID */ @Override protected Object contextKey() { TestCaseInfo testCaseInfo = this.getClass().getAnnotation(TestCaseInfo.class); if (!testCaseInfo.autoWire()) { return null; } if ((testCaseInfo != null) && (testCaseInfo.contextKey() != null) && (testCaseInfo.contextKey().length() != 0)) { return testCaseInfo.contextKey(); } else { if (testCaseInfo.useDataSourceContextKey()) { return "DatasourceServicesLocator"; } throw new RuntimeException( "You SHOULD override contextKey() or add TestCaseInfo to the test class or set autoWire false or add useDataSourceContextKey=true."); } } /** * ??Spring */ @Override protected ConfigurableApplicationContext loadContext(Object key) throws Exception { return (ConfigurableApplicationContext) CommonServiceLocator.getApplicationContext(); } /** * ? * * <pre> * {@link TestCaseInfo#autoWire()}{@link AbstractDependencyInjectionSpringContextTests#prepareTestInstance()} ? * dataSourcetranscationManager. * </pre> */ @Override protected void prepareTestInstance() throws Exception { TestCaseInfo testCaseInfo = this.getClass().getAnnotation(TestCaseInfo.class); this.initMoke(); this.setDependencyCheck(false); // ?? if (testCaseInfo.autoWire()) { this.setAutowireMode(testCaseInfo.autoWireMode()); } else { this.setAutowireMode(AUTOWIRE_NO); } // jdbcExtractor // if ((testCaseInfo == null) || testCaseInfo.useJdbcExtractor()) { // this.applicationContext.getBean("jdbcExtractor"); // } // AbstractDependencyInjectionSpringContextTests ? super.prepareTestInstance(); afterPrepareTestInstance(); // Mock current test instance. if (isMockOn()) { AliMock.mockObject(this); } } protected void afterPrepareTestInstance() { } /** * Service??? * * @throws InstantiationException * @throws IllegalAccessException */ protected void initMoke() throws InstantiationException, IllegalAccessException { // Mock once on startup if (isMockOn()) { if (log.isDebugEnabled()) { log.debug("================>initMock!"); } ConfigurableApplicationContext context = (ConfigurableApplicationContext) CommonServiceLocator .getApplicationContext(); context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.addBeanPostProcessor(new MockBeanPostProcessor()); } }); context.refresh(); } } @Override protected void onSetUpBeforeTransaction() throws Exception { if (getClass().getAnnotation(TestCaseInfo.class) != null) { if (!getClass().getAnnotation(TestCaseInfo.class).defaultRollBack()) { log.warn("Set default rollback to false."); } setDefaultRollback(getClass().getAnnotation(TestCaseInfo.class).defaultRollBack()); } if ((getClass().getAnnotation(SecondaryJdbcSetting.class) != null) && (jdbcManagementTool == null)) { SecondaryJdbcSetting setting = getClass().getAnnotation(SecondaryJdbcSetting.class); if (setting.jdbcManagementToolBuilder() == JdbcManagementToolBuilder.class) { jdbcManagementTool = new JdbcManagementTool(setting); jdbcManagementTool .setDefaultRollback(getClass().getAnnotation(TestCaseInfo.class).defaultRollBack()); } else { jdbcManagementTool = ReflectUtil.newInstance(setting.jdbcManagementToolBuilder()) .buildJdbcManagementTool(this); } } if (jdbcManagementTool != null) { jdbcManagementTool.startTransaction(); SecondarySetting secondarySetting = null; Method method = ThreadContextCache.get(Method.class, BuiltInCacheKey.Method); final PrepareAnnotationTool prepareAnnotation = new PrepareAnnotationTool(method); if (prepareAnnotation != null) { if (prepareAnnotation.secondaryPrepareFilter() != SecondaryPreareFilter.class) { final SecondaryPreareFilter secondaryPreareFilter = ReflectUtil .newInstance(prepareAnnotation.secondaryPrepareFilter()); secondarySetting = new SecondarySetting(jdbcManagementTool, secondaryPreareFilter); } } if (secondarySetting == null) { SecondaryJdbcSetting secondaryJdbcSetting = getClass().getAnnotation(SecondaryJdbcSetting.class); secondarySetting = new SecondarySetting(jdbcManagementTool, ReflectUtil.newInstance(secondaryJdbcSetting.secondaryPrepareFilter())); } ThreadContextCache.put(BuiltInCacheKey.SecondarySetting, secondarySetting); } } /** * ??? */ // @Override // protected void startNewTransaction() throws TransactionException { // // // super.startNewTransaction(); // // ?? // try { // before(); // } catch (Exception e) { // throw new RuntimeException("Init Test Data Failed", e); // } // } @Override protected void onTearDownAfterTransaction() throws Exception { if (jdbcManagementTool != null) { jdbcManagementTool.finishTrasaction(); ThreadContextCache.put(BuiltInCacheKey.SecondarySetting, null); } } @Before public void before() throws Exception { log.debug("BaseTestCase.before()"); TestCaseInfo testCaseInfo = this.getClass().getAnnotation(TestCaseInfo.class); if (testCaseInfo.autoWire()) { this.applicationContext = getContext(contextKey()); prepareTestInstance(); } onSetUp(); initOnBeforeEveryTestCase(); if (!firstTimeRan) { // ? firstTimeRan = true; runOnceBeforeAll(); } } @After @SuppressWarnings("unchecked") public void after() throws Exception { log.debug("=========================> BaseTestCase.after()"); if (ThreadContextCache.get(BuiltInCacheKey.Finally) != null) { for (Runnable runnable : (List<Runnable>) ThreadContextCache.get(List.class, BuiltInCacheKey.Finally)) { try { runnable.run(); } catch (Exception e) { log.error("Error occured in clear data.", e); } } } final List<Task> taskList = (List<Task>) TestCaseRuntimeInfo.current().getContext() .get(ClearSpecialDataPrepareEvent.__finish__task__list__); if (taskList != null) { if (TestCaseRuntimeInfo.current().getPrepare().newThreadTransactionImport()) { runInBlockedThread(new Runnable() { public void run() { log.warn("Clear data in new thread (transaction)."); TransactionStatus localTransactionStatus = transactionManager .getTransaction(new DefaultTransactionDefinition()); try { TaskUtil.runTasks(taskList); transactionManager.commit(localTransactionStatus); } catch (Throwable t) { log.error("Clear data transaction has be rolled back.", t); transactionManager.rollback(localTransactionStatus); throw new RuntimeException(t); } } }); } else { TaskUtil.runTasks(taskList); } } super.tearDown(); if (isMockOn()) { AliMock.clearMock(); } objectMethodMap.clear(); ThreadContextCache.clear(); } // ? // ================================================================================ /** * ?? */ protected void runOnceBeforeAll() { } // ================================================================================ /** * ?? */ protected Class<?> clazz() { TestCaseInfo tci = this.getClass().getAnnotation(TestCaseInfo.class); if ((tci == null) || (tci.testFor() == TestCase.class)) { String testClassName = this.getClass().getName(); if (testClassName.endsWith("Test")) { try { return Class.forName(testClassName.substring(0, testClassName.length() - 4)); } catch (ClassNotFoundException e) { System.err.println( "Load class failed: " + testClassName.substring(0, testClassName.length() - 4)); } } throw new RuntimeException("No TestCaseInfo or not assigned For class."); } return tci.testFor(); } /** * ?(non-static ) */ protected Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters) { if (object instanceof Proxy) { object = ProxyDepackageUtil.getLastDepackageObject(object); } Class<?> clazz = object.getClass(); return ReflectUtil.invokeMethod(clazz, object, methodName, parameterTypes, parameters); } /** * {@link BaseTestCase#invokeMethod(Object, String, Class[], Object[])}?? * * @param object * @param methodName * @return */ protected Object invokeMethod(Object object, String methodName) { return invokeMethod(object, methodName, null, null); } /** * ?(static ) */ protected Object invokeMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object[] parameters) { return ReflectUtil.invokeMethod(clazz, null, methodName, parameterTypes, parameters); } /** * {@link BaseTestCase#invokeMethod(Class, String, Class[], Object[])}?? * * @param clazz * @param methodName * @return */ protected Object invokeMethod(Class<?> clazz, String methodName) { return invokeMethod(clazz, methodName, null, null); } /** * * * @return */ protected Object[] nulls() { return new Object[] { null }; } /** * * * @param methodName * @param params * @return */ protected Object callStatic(String methodName, Object... params) { return callMethod(null, methodName, params); } /** * * * @param obj * @param methodName * @param params * @return */ protected Object callMethod(Object obj, String methodName, Object... params) { Class<?> clazz = (obj == null) ? clazz() : ((obj instanceof Class<?>) ? (Class<?>) obj : obj.getClass()); for (Method method : clazz.getDeclaredMethods()) { if (method.getName().equals(methodName)) { if (method.getParameterTypes().length == params.length) { method.setAccessible(true); try { if ((obj == null) || (obj instanceof Class<?>)) { return method.invoke(null, params); } else { return method.invoke(obj, params); } } catch (Exception e) { throw ExceptionUtil.wrapToRuntimeException(e); } } } } throw new RuntimeException("Cannot find method '" + methodName + "' in '" + clazz + "'."); } // ================================================================================ /** * */ protected File requireTempFile(String fileName) { return new File(IntlTestGlobalConstants.TESTCASE_USER_TEMP_DIR + File.separator + fileName); } /** * ? * * @param fileName * @return */ protected File requireDataFile(String fileName) { return new File(BaseReaderUtil.getBasePath() + fileName); } // ================================================================================ /** * ??? */ protected void sortList(List<?> list, String sortField) { SortUtil.sortList(list, sortField, true); } /** * ??? */ protected void sortList(List<?> list, String sortField, boolean asc) { SortUtil.sortList(list, sortField, asc); } /** * () */ @SuppressWarnings("unchecked") protected <T> T getObject(Object object, String fieldName) { Class<?> clazz = (object.getClass() == Class.class) ? (Class<?>) object : object.getClass(); try { Field field = ReflectUtil.getDeclaredField(clazz, fieldName); field.setAccessible(true); if (Modifier.isStatic(field.getModifiers())) { return (T) field.get(null); } else { return (T) field.get(object); } } catch (Exception e) { throw new RuntimeException(e); } } /** * () */ protected void setObject(Object object, String fieldName, Object value) { Class<?> clazz = (object.getClass() == Class.class) ? (Class<?>) object : object.getClass(); try { Field field = ReflectUtil.getDeclaredField(clazz, fieldName); field.setAccessible(true); if (Modifier.isStatic(field.getModifiers())) { field.set(null, value); } else { field.set(object, value); } } catch (Exception e) { throw new RuntimeException(e); } } /** * ??? * * @param object * @param fieldName * @param value */ protected void replaceObjectInTestCase(final Object object, final String fieldName, Object value) { final Object oldValue = getObject(object, fieldName); setObject(object, fieldName, value); List<Object> listKey = Arrays.asList(object, fieldName); if (objectMethodMap.get(listKey) == null) { objectMethodMap.put(listKey, Boolean.TRUE); // ?? clearDataAtFinally(new Runnable() { public void run() { setObject(object, fieldName, oldValue); } }); } } // ================================================================================ /** * prepare??? */ protected void prepareDataBase(String... tables) { PrepareUtil.prepareDataBase(jdbcTemplate, getMemoryDB(), tables); } protected <T> T prepareObject(Class<T> clazz, String table) { return PrepareUtil.prepareObject(getMemoryDB(), clazz, table); } /** * prepare?java pojo */ protected <T> List<T> prepareObjectList(Class<T> clazz, String table) { return PrepareUtil.prepareObjectList(getMemoryDB(), clazz, table); } /** * prepare?java pojo */ protected <T> T prepareObject(Class<T> clazz, String database, String table) { return PrepareUtil.prepareObject(getMemoryDB(database), clazz, table); } /** * database?java pojo */ protected <T> List<T> prepareObjectList(Class<T> clazz, String database, String table) { return PrepareUtil.prepareObjectList(getMemoryDB(database), clazz, table); } // ================================================================================ /** * database?java pojo */ private <T> boolean checkBothNull(List<T> expected, List<T> actual) { if (expected == null) { assertNull("expected is null but actual is not null", actual); return true; } else if (actual == null) { fail("expected is not null but actual is null"); } return false; } /** * expectedactual??null */ protected <T> void assertListEquals(List<T> expected, List<T> actual) { if (checkBothNull(expected, actual)) return; assertEquals("Size not equals", expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { assertEquals("Index " + i + " assert failed", expected.get(i), actual.get(i)); } } /** * list??list(ArrayListLinkedList) */ protected <T> void assertListEquals(List<T> expected, List<T> actual, Comparator<T> comparator) { if (checkBothNull(expected, actual)) return; assertEquals("Size not equals", expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { assertTrue("Index " + i + " assert failed", comparator.compare(expected.get(i), actual.get(i))); } } /** * list???listComparable?IntegerString */ protected <T extends Comparable<? super T>> void assertListSortedEquals(List<T> expected, List<T> actual) { if (checkBothNull(expected, actual)) return; assertEquals("Size not equals", expected.size(), actual.size()); Collections.sort(expected); Collections.sort(actual); for (int i = 0; i < expected.size(); i++) { assertEquals("Index " + i + " assert failed", expected.get(i), actual.get(i)); } } /** * list???list???java.util.Comparator?? */ protected <T> void assertListSortedEquals(List<T> expected, List<T> actual, java.util.Comparator<T> comparator) { if (checkBothNull(expected, actual)) return; assertEquals("Size not equals", expected.size(), actual.size()); Collections.sort(expected, comparator); Collections.sort(actual, comparator); for (int i = 0; i < expected.size(); i++) { assertEquals("Index " + i + " assert failed", expected.get(i), actual.get(i)); } } /** * list???list???sortField?????? */ protected <T> void assertListSortedEquals(List<T> expected, List<T> actual, String sortField) { assertListSortedEquals(expected, actual, sortField, true); } /** * list???list???sortField????asc??/?? */ protected <T> void assertListSortedEquals(List<T> expected, List<T> actual, String sortField, boolean asc) { if (checkBothNull(expected, actual)) return; assertEquals("Size not equals", expected.size(), actual.size()); SortUtil.sortList(expected, sortField, asc); SortUtil.sortList(actual, sortField, asc); for (int i = 0; i < expected.size(); i++) { assertEquals("Index " + i + " assert failed", expected.get(i), actual.get(i)); } } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ???API <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /** * ? * * * @return */ protected JavaBeanPreparation getObjPreparation() { return (new JavaBeanPreparation()).database(getMemoryDB()); } protected YamlPreparation getYamlPreparation(String dataFileName) { return new YamlPreparation().relativePath(getRelativePath(DataReaderType.Yaml, dataFileName)); } /** * ?? * * * @return */ protected DataBasePreparation getDBPreparation() { return (new DataBasePreparation()).jdbcTemplate(jdbcTemplate).database(getMemoryDB()); } /** * ForEach? * * * @param <T> * @return */ protected <T> ForEachPreparation<T> getForPreparation() { return new ForEachPreparation<T>(); } /** * ??? * * * @return */ protected DataBaseAssertion getDBAssertion() { return (new DataBaseAssertion()).jdbcTemplate(jdbcTemplate) .database(getMemoryDB(BuiltInCacheKey.Result.getValue())); } /** * ?? * * * @return */ protected JavaBeanAssertion getObjAssertion() { return (new JavaBeanAssertion()).database(getMemoryDB(BuiltInCacheKey.Result.getValue())); } /** * ??memorydatabase? * * @return */ protected ParameterizedAssertion getParamAssertion() { return (new ParameterizedAssertion()).database(getMemoryDB()); } /** * ForEach?? * * * @param <T> * @return */ protected <T> ForEachAssertion<T> getForAssertion() { return new ForEachAssertion<T>(); } /** * ?? */ protected void assertSuccessed() { // do nothing } /** * Assert string is blank: whitespace, empty ("") or null */ protected void assertBlank(String str) { assertTrue(StringUtils.isBlank(str)); } /** * Assert string is empty ("") or null */ protected void assertEmpty(String str) { assertTrue(StringUtils.isEmpty(str)); } /** * Assert string is not blank */ protected void assertNotBlank(String str) { assertTrue(StringUtils.isNotBlank(str)); } /** * Assert string is not empty */ protected void assertNotEmpty(String str) { assertTrue(StringUtils.isNotEmpty(str)); } /** * Assert string contains only unicode digits. */ protected void assertNumeric(String str) { assertTrue(StringUtils.isNumeric(str)); } /** * Assert string contains only unicode digits or space(' '). */ protected void assertNumericSpace(String str) { assertTrue(StringUtils.isNumericSpace(str)); } /** * Assert string contains only whitespace. */ protected void assertWhitespace(String str) { assertTrue(StringUtils.isWhitespace(str)); } /** * Assert array is null or empty(length==0) */ protected <T> void assertNullOrEmpty(T[] array) { assertTrue(array == null || array.length == 0); } /** * Assert list is null or empty */ protected <T> void assertNullOrEmpty(List<T> list) { assertTrue(list == null || list.isEmpty()); } /** * result?(??)java pojo */ protected void assertResult(Object bean) { Assert.assertResult(getMemoryDB(BuiltInCacheKey.Result.getValue()), bean); } /** * result?java pojo * * @param bean * @param table */ protected void assertResult(Object bean, String table) { Assert.assertResult(getMemoryDB(BuiltInCacheKey.Result.getValue()), bean, table); } /** * result?(??)java pojo */ protected void assertResultList(List<?> beanList) { Assert.assertResultList(getMemoryDB(BuiltInCacheKey.Result.getValue()), beanList); } /** * result?java pojo */ protected void assertResultList(List<?> beanList, String table) { Assert.assertResultList(getMemoryDB(BuiltInCacheKey.Result.getValue()), beanList, table); } /** * result?java pojo,? */ protected void assertResultList(List<?> beanList, String table, String[] columns) { Assert.assertResultList(getMemoryDB(BuiltInCacheKey.Result.getValue()), beanList, table, columns); } /** * result?(??)??java pojolist */ protected void assertResultListSorted(List<?> beanList, String sortField) { assertResultListSorted(beanList, sortField, true); } /** * result?(??)??java pojolist */ protected void assertResultListSorted(List<?> beanList, String sortField, boolean asc) { SortUtil.sortList(beanList, sortField, asc); assertResultList(beanList); } /** * result???java pojolist */ protected void assertResultListSorted(List<?> beanList, String table, String sortField) { assertResultListSorted(beanList, table, sortField, true); } /** * result???java pojolist */ protected void assertResultListSorted(List<?> beanList, String table, String sortField, boolean asc) { SortUtil.sortList(beanList, sortField, asc); assertResultList(beanList, table); } /** * result???java pojolist,? */ protected void assertResultListSorted(List<?> beanList, String table, String[] columns, String sortField) { assertResultListSorted(beanList, table, columns, sortField, true); } /** * result???java pojolist,? */ protected void assertResultListSorted(List<?> beanList, String table, String[] columns, String sortField, boolean asc) { SortUtil.sortList(beanList, sortField, asc); assertResultList(beanList, table, columns); } /** * database?(??)java pojo */ public void assertResultList(String database, List<?> beanList) { Assert.assertResultList(getMemoryDB(database), beanList); } /** * database?java pojo */ protected void assertResultList(String database, List<?> beanList, String table) { Assert.assertResultList(getMemoryDB(database), beanList, table); } /** * database?(??)??java pojolist */ public void assertResultListSorted(String database, List<?> beanList, String sortField) { assertResultListSorted(database, beanList, sortField, true); } /** * database?(??)??java pojolist */ public void assertResultListSorted(String database, List<?> beanList, String sortField, boolean asc) { SortUtil.sortList(beanList, sortField, asc); assertResultList(database, beanList); } /** * database???java pojolist */ protected void assertResultListSorted(String database, List<?> beanList, String table, String sortField) { assertResultListSorted(database, beanList, table, sortField, true); } /** * database???java pojolist */ protected void assertResultListSorted(String database, List<?> beanList, String table, String sortField, boolean asc) { SortUtil.sortList(beanList, sortField, asc); assertResultList(database, beanList, table); } /** * result??? */ protected void assertResultTable(String table) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(BuiltInCacheKey.Result.getValue()), table); } /** * result???,? */ protected void assertResultTable(String table, String[] columns) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(BuiltInCacheKey.Result.getValue()), table, columns); } /** * result???(????) */ protected void assertResultTable(String table, String whereSql, String sortSql, Object[] args) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(BuiltInCacheKey.Result.getValue()), table, whereSql, sortSql, args); } /** * result???(????) */ protected void assertResultTable(String table, String whereSql, String sortSql, Object[] args, String[] columns) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(BuiltInCacheKey.Result.getValue()), table, whereSql, sortSql, args, columns); } /** * database?(??)java pojo */ protected void assertResult(String database, Object bean) { Assert.assertResult(getMemoryDB(database), bean); } /** * database?java pojo * * @param bean * @param table */ protected void assertResult(String database, Object bean, String table) { Assert.assertResult(getMemoryDB(database), bean, table); } /** * database??? */ protected void assertResultTable(String database, String table) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(database), table); } /** * * database???(????) */ protected void assertResultTable(String database, String table, String whereSql, String sortSql, Object[] args) { Assert.assertResultTable(jdbcTemplate, getMemoryDB(database), table, whereSql, sortSql, args); } /** * ?? */ protected void assertResultTableEmpty(String table) { assertResultTableCount(table, 0); } /** * ??? */ protected void assertResultTableEmpty(String table, String where) { assertResultTableCount(table, where, 0); } /** * ?? */ protected void assertResultTableCount(String table, int count) { assertResultTableCount(table, null, count); } /** * ??? */ protected void assertResultTableCount(String table, String where, int count) { String w = ((where == null) || (where.length() == 0)) ? "1=1" : where; String we = (where == null) ? "" : where; int c = jdbcTemplate.queryForInt("select count(*) from " + table + " where " + w); if (c != count) { throw new AssertException("Aspect table `" + table + "` have " + count + " recoreds on `" + we + "` but actual have " + c + " records."); } } // ================================================================================ /** * ?prepare?? */ protected MemoryDatabase getMemoryDB() { MemoryDatabase database = ThreadContextCache.get(MemoryDatabase.class, BuiltInCacheKey.Prepare.getValue()); if (database == null) { throw new RuntimeException("Memory database not prepared or prepare file not exists."); } return database; } /** * ????? */ protected MemoryDatabase getMemoryDB(String dataFileName) { Method method = ThreadContextCache.get(Method.class, BuiltInCacheKey.Method); return getMemoryDB(getDataReaderType(method), dataFileName); } /** * ?????? */ protected MemoryDatabase getMemoryDB(DataReaderType dataType, String dataFileName) { return getMemoryDB(dataType, dataFileName, true); } /** * * ??????(????) */ protected MemoryDatabase getMemoryDB(DataReaderType dataType, String dataFileName, boolean checkFileExists) { MemoryDatabase cachedDataBase = ThreadContextCache.get(MemoryDatabase.class, dataFileName); if (cachedDataBase != null) { return cachedDataBase; } String relativePath = getRelativePath(dataType, dataFileName); try { MemoryDatabase database = (MemoryDatabase) DataReaderUtil.readData(dataType, relativePath); ThreadContextCache.put(dataFileName, database); return database; } catch (ResourceNotFoundException e) { e.printStackTrace(); if (checkFileExists) { throw e; } else { return null; } } } // ================================================================================ /** * ?? */ protected void clearTables(String... tables) { for (String table : tables) { clearTableData(table); } } /** * ??<br> * ?spring??deleteFromTables * * @see AbstractTransactionalDataSourceSpringContextTests#deleteFromTables(String[]) */ protected void clearTableData(String table) { clearTableData(table, "1=1"); } /** * ??(whereSql ?1=1)<br> * ?spring??deleteFromTables * * @see AbstractTransactionalDataSourceSpringContextTests#deleteFromTables(String[]) */ protected void clearTableData(String table, String whereSql) { if ((whereSql == null) || (whereSql.length() == 0)) { throw new RuntimeException("Where sql cannot be empty."); } int count = jdbcTemplate.update("delete from " + table + " where " + whereSql); log.info("Table `" + table + "` 's `" + count + "` records has been cleared on `" + whereSql + "`."); } // ================================================================================ /** * ?? */ protected void runInBlockedThread(final Runnable runnable) { final List<Throwable> throwable = new ArrayList<Throwable>(); Thread blockedThread = new Thread(new Runnable() { public void run() { try { runnable.run(); } catch (Throwable t) { throwable.add(t); } } }); blockedThread.start(); try { blockedThread.join(); } catch (InterruptedException e) { log.error("Thread interrupted error occured in blocked thread runing.", e); throw new RuntimeException(e); } if (throwable.size() > 0) { Throwable t = throwable.get(0); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new RuntimeException(throwable.get(0)); } } } /** * */ @SuppressWarnings("unchecked") protected void clearDataAtFinally(Runnable runnable) { if (ThreadContextCache.get(BuiltInCacheKey.Finally) == null) { ThreadContextCache.put(BuiltInCacheKey.Finally, new ArrayList<Runnable>()); } ThreadContextCache.get(List.class, BuiltInCacheKey.Finally).add(runnable); } // ================================================================================ // {{{{{{{{{{{{{{{{ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }}}}}}}}}}}}}}}} // protected void initOnBeforeEveryTestCase() { log.debug("=========================> BaseTestCase.initOnBeforeEveryTestCase() init db data"); String basePath = getClassBasePath(); if (basePath.contains("com.mountainminds.eclemma.core")) { // if run in eclemma System.err.println("Run in eclemma we try to change base path!"); String userDir = IntlTestGlobalConstants.USER_DIR; if (new File(FilenameUtils.concat(userDir, "src/java")).exists()) { basePath = getFinalClassBasePath(userDir + "/src/java.test/"); } else if (new File(FilenameUtils.concat(userDir, "src/main")).exists()) { basePath = getFinalClassBasePath(userDir + "/src/test/java"); } else { System.err.println("Oh, we cannot detect is antx or maven."); } } log.info("Base path set to `" + basePath + "`."); BaseReaderUtil.setBasePath(basePath); initMemoryDatabaseOnBeforeEveryTestCase(); } // called by prepare class runner protected void initMemoryDatabaseOnBeforeEveryTestCase() { Method method = ThreadContextCache.get(Method.class, BuiltInCacheKey.Method); if (!isNeedPrepare(method)) { return; } // ?handle DbEncodingUtil.clearInfo(); final PrepareAnnotationTool prepareAnnotation = new PrepareAnnotationTool(method); // xml_tree???MemoryDatabase if (DataReaderType.TreeXml == prepareAnnotation.type()) { return; } // ? DbEncodingUtil.applyInfo(new CnStringDbEncodingInfo(prepareAnnotation.cnStringEncoding())); DbEncodingUtil.applyInfo(new UTF8StringDbEncodingInfo(prepareAnnotation.utf8StringEncoding())); // ?Sheet final String[] importTables = StringUtil.splitAndTrimByComma(prepareAnnotation.importTables()); PrepareEventUtil.clearRegister(); if (prepareAnnotation.autoClearExistsData() || prepareAnnotation.autoClearImportDataOnFinish()) { log.info("Import data clear exists ones on."); PrepareEventUtil.register(new ClearSpecialDataPrepareEvent(prepareAnnotation.primaryKey())); } final MemoryDatabase prepare = getMemoryDB(prepareAnnotation.type(), BuiltInCacheKey.Prepare.getValue(), true); getMemoryDB(prepareAnnotation.type(), BuiltInCacheKey.Result.getValue(), false); // common prepare (for test case class) MemoryDatabase commonPrepare = null; if (prepareAnnotation.autoImportCommonData()) { commonPrepare = getMemoryDB(prepareAnnotation.type(), ":prepare", false); } final MemoryDatabase finalCommonPrepare = commonPrepare; if (prepareAnnotation.autoImport()) { boolean isDefaultRollback = isDefaultRollback(); if (prepareAnnotation.autoClear()) { if ((!isDefaultRollback) || (prepareAnnotation.newThreadTransactionImport())) { if (!prepareAnnotation.forceClear()) { throw new RuntimeException("Cannot import data when default rollback was" + " turned off and no force clear flag."); } } } log.info("Auto import data on flag autoImport:" + prepareAnnotation.autoImport() + ", autoClear:" + prepareAnnotation.autoClear() + ", defaultRollback:" + isDefaultRollback + ", forceClear:" + prepareAnnotation.forceClear() + ", newThreadTransactionImport:" + prepareAnnotation.newThreadTransactionImport()); if (prepareAnnotation.newThreadTransactionImport()) { runInBlockedThread(new Runnable() { public void run() { log.warn("Import data in new thread (transaction)."); TransactionStatus localTransactionStatus = transactionManager .getTransaction(new DefaultTransactionDefinition()); try { if (prepareAnnotation.autoImportCommonData() && (finalCommonPrepare != null)) { PrepareUtil.prepareDataBase(jdbcTemplate, finalCommonPrepare, prepareAnnotation.autoClear()); } if (importTables != null) { PrepareUtil.prepareDataBase(jdbcTemplate, prepare, prepareAnnotation.autoClear(), importTables); } else { PrepareUtil.prepareDataBase(jdbcTemplate, prepare, prepareAnnotation.autoClear()); } log.info("Import data transaction has be commited."); transactionManager.commit(localTransactionStatus); } catch (Throwable t) { log.error("Import data transaction has be rolled back.", t); transactionManager.rollback(localTransactionStatus); throw new RuntimeException(t); } } }); } else { if (prepareAnnotation.autoImportCommonData() && (finalCommonPrepare != null)) { PrepareUtil.prepareDataBase(jdbcTemplate, finalCommonPrepare, prepareAnnotation.autoClear()); } if (importTables != null) { PrepareUtil.prepareDataBase(jdbcTemplate, prepare, prepareAnnotation.autoClear(), importTables); } else { PrepareUtil.prepareDataBase(jdbcTemplate, prepare, prepareAnnotation.autoClear()); } } } } protected String getAbstractBasePath() { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String slashClassName = this.getClass().getName().replace('.', '/'); String classPath = classLoader.getResource(slashClassName + ".class").getPath(); int classIndex = classPath.indexOf(slashClassName); String basePart = classPath.substring(0, classIndex); return basePart; } protected String getClassBasePath() { TestCaseInfo info = this.getClass().getAnnotation(TestCaseInfo.class); if ((info != null) && (info.basePath().length() != 0)) { return info.basePath(); } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String slashClassName = this.getClass().getName().replace('.', '/'); String classPath = classLoader.getResource(slashClassName + ".class").getPath(); int classIndex = classPath.indexOf(slashClassName); String basePart = classPath.substring(0, classIndex); return getFinalClassBasePath(basePart); } protected String getFinalClassBasePath(String basePart) { String slashClassName = this.getClass().getName().replace('.', '/'); String finalPath = basePart + "/" + getResourcePrefix() + "/" + slashClassName + getClassSuffix(); finalPath = replaceDoubleSlash(finalPath); if ((new File(finalPath)).exists()) { return finalPath; } else { String newPath = basePart + "/" + getResourcePrefix() + "/" + nomalnizeClassPath(slashClassName) + getClassSuffix(); return replaceDoubleSlash(newPath); } } protected String replaceDoubleSlash(String path) { while (path.indexOf("//") >= 0) { path = path.replace("//", "/"); } return path; } protected String nomalnizeClassPath(String path) { if (path == null) { return null; } String[] parts = path.split("[\\/]"); StringBuilder newPath = new StringBuilder(); for (int i = 0; i < parts.length; i++) { String part = parts[i]; if ((part != null) && part.length() > 0) { newPath.append(part.substring(0, 1).toLowerCase() + part.substring(1)); } if (i < (parts.length - 1)) { newPath.append("/"); } } return newPath.toString(); } protected String getRelativePath(DataReaderType dataType, String dataFileName) { if (dataFileName.startsWith(":")) { dataFileName = dataFileName.substring(1); } else { String methodName = getMethodName(); if (dataFileName.indexOf('_') <= 0) { dataFileName = methodName + "_" + dataFileName; } } String defaultExt = DataReaderUtil.getDefaultExt(dataType); String relativePath = dataFileName; if (!relativePath.endsWith(defaultExt)) { relativePath = relativePath + defaultExt; } return relativePath; } protected String getMethodName() { Method method = ThreadContextCache.get(Method.class, BuiltInCacheKey.Method); PrepareAnnotationTool prepare = new PrepareAnnotationTool(method); if ((prepare != null) && (prepare.methodName().length() != 0)) { return prepare.methodName(); } else { return ThreadContextCache.get(Method.class, BuiltInCacheKey.Method).getName(); } } protected String getResourcePrefix() { TestCaseInfo info = this.getClass().getAnnotation(TestCaseInfo.class); return ((info == null) || (info.defaultPath())) ? "" : info.pathPrefix(); } protected String getClassSuffix() { TestCaseInfo info = this.getClass().getAnnotation(TestCaseInfo.class); return ((info == null) || (info.defaultPath())) ? DEFAULT_CLASS_SUFFIX : info.classSuffix(); } protected DataReaderType getDataReaderType(Method method) { PrepareAnnotationTool prepare = new PrepareAnnotationTool(method); return prepare.type(); } protected boolean isNeedPrepare(Method method) { return new PrepareAnnotationTool(method).isPrepareEnable(); } protected boolean isMockOn() { boolean isMockFlagOn = (this.getClass().getAnnotation(Mock.class) != null); // ?MOCKMock return isMockFlagOn; } protected boolean isDefaultRollback() { try { Field defaultRollbackField = AbstractTransactionalSpringContextTests.class .getDeclaredField("defaultRollback"); defaultRollbackField.setAccessible(true); return ((Boolean) defaultRollbackField.get(this)).booleanValue(); } catch (Exception e) { throw new RuntimeException(e); } } // ================================================================================ // ???,?memorydatabase?memorydatabase protected TreeDatabase getTreeDB() { return getTreeDB(BuiltInCacheKey.Prepare.getValue()); } protected TreeDatabase getTreeDB(String dataFileName) { return getTreeDB(dataFileName, true); } protected TreeDatabase getTreeDB(String dataFileName, boolean checkFileExists) { String relativePath = getRelativePath(DataReaderType.TreeXml, dataFileName); try { TreeDatabase database = (TreeDatabase) DataReaderUtil.readData(DataReaderType.TreeXml, relativePath); return database; } catch (ResourceNotFoundException e) { if (checkFileExists) { throw e; } else { return null; } } } /** * ???? * * @param database getTreeDB() * @param objectName TreeObject.name * @return */ protected static Object prepareObject(TreeDatabase database, String objectName) { List<?> treeObjectList = prepareObjectList(database, objectName); if (treeObjectList != null && treeObjectList.size() > 0) { return treeObjectList.get(0); } return null; } /** * ??? * * @param database getTreeDB() * @param objectName TreeObject.name * @return */ protected static List<?> prepareObjectList(TreeDatabase database, String objectName) { TreeObject treeTable = database.getObject(objectName); if (treeTable != null) { return treeTable.getTreeObjectList(); } return null; } /** * <strong><font color=red> NEW FEATURE?</font></strong><code>?<br> * * <pre> * PersonProfile{ * String firstName; * String lastName; * Date gmtCreate; * List<Integer> list; * }; * Person{ * Integer id; * Date gmtModified; * PersonProfile personProfile; * }; * </pre> * * @param bean ?result * @param objectName result?? * @param properties : ?Person?: * {"id","personProfile.gmtCreate","personProfile.list"}??inclusiveexclusive?? * @param exclusive true<strong><font color=red>?</font></strong><code>properties</code> * false<strong><font color=red>?</font></strong> <code>properties</code> */ protected void assertTreeObjectResult(Object bean, String objectName, String[] properties, boolean exclusive) { TreeObjectAssert.assertResult(getTreeDB(BuiltInCacheKey.Result.getValue()), bean, objectName, properties, exclusive); } /** * <strong><font color=red> NEW FEATURE?</font></strong><code>?<br> * * <pre> * PersonProfile{ * String firstName; * String lastName; * Date gmtCreate; * List<Integer> list; * }; * Person{ * Integer id; * Date gmtModified; * PersonProfile personProfile; * }; * </pre> * * @param beanlist ?result * @param objectName result?? * @param properties : ?Person?: * {"id","personProfile.gmtCreate","personProfile.list"}??inclusiveexclusive?? * @param exclusive true<strong><font color=red>?</font></strong><code>properties</code> * false<strong><font color=red>?</font></strong> <code>properties</code> */ protected void assertTreeObjectResultList(List<?> beanList, String objectName, String[] properties, boolean exclusive) { TreeObjectAssert.assertResultList(getTreeDB(BuiltInCacheKey.Result.getValue()), beanList, objectName, properties, exclusive); } /** * <strong><font color=red> NEW FEATURE?</font></strong><code>?<br> * * <pre> * PersonProfile{ * String firstName; * String lastName; * Date gmtCreate; * List<Integer> list; * }; * Person{ * Integer id; * Date gmtModified; * PersonProfile personProfile; * }; * </pre> * * @param object1 * @param object2 * @param properties : ?Person?: * {"id","personProfile.gmtCreate","personProfile.list"}??inclusiveexclusive?? * @param exclusive true<strong><font color=red>?</font></strong><code>properties</code> * false<strong><font color=red>?</font></strong> <code>properties</code> */ protected void assertObjectEquals(Object object1, Object object2, String[] properties, boolean exclusive) { if (!JsonObjectUtils.isSameObject(object1, object2, properties, exclusive)) { throw new AssertException("Not equals!"); } } }