/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.configuration.xml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.aop.framework.Advised;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.job.AbstractJob;
import org.springframework.batch.core.listener.CompositeStepExecutionListener;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.core.step.item.FatalRuntimeException;
import org.springframework.batch.core.step.item.FatalSkippableException;
import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
import org.springframework.batch.core.step.item.SkippableException;
import org.springframework.batch.core.step.item.SkippableRuntimeException;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.core.step.tasklet.TaskletStep;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.support.CompositeItemStream;
import org.springframework.batch.repeat.CompletionPolicy;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.retry.RetryListener;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
/**
* @author Thomas Risberg
* @author Dan Garrette
*/
public class StepParserTests {
private static ApplicationContext stepParserParentAttributeTestsCtx;
@BeforeClass
public static void loadAppCtx() {
stepParserParentAttributeTestsCtx = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml");
}
@Test
@SuppressWarnings("resource")
public void testTaskletStepAttributes() throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml");
@SuppressWarnings({ "rawtypes" })
Map<String, StepParserStepFactoryBean> beans = ctx.getBeansOfType(StepParserStepFactoryBean.class);
String factoryName = (String) beans.keySet().toArray()[0];
@SuppressWarnings("unchecked")
StepParserStepFactoryBean<Object, Object> factory = beans.get(factoryName);
TaskletStep bean = (TaskletStep) factory.getObject();
assertEquals("wrong start-limit:", 25, bean.getStartLimit());
Object throttleLimit = ReflectionTestUtils.getField(factory, "throttleLimit");
assertEquals(new Integer(10), throttleLimit);
}
@Test
@SuppressWarnings("resource")
public void testStepParserBeanName() throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserBeanNameTests-context.xml");
Map<String, Step> beans = ctx.getBeansOfType(Step.class);
assertTrue("'s1' bean not found", beans.containsKey("s1"));
Step s1 = (Step) ctx.getBean("s1");
assertEquals("wrong name", "s1", s1.getName());
}
@Test(expected = BeanDefinitionParsingException.class)
@SuppressWarnings("resource")
public void testStepParserCommitIntervalCompletionPolicy() throws Exception {
new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserCommitIntervalCompletionPolicyTests-context.xml");
}
@Test
@SuppressWarnings("resource")
public void testStepParserCommitInterval() throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserCommitIntervalTests-context.xml");
Map<String, Step> beans = ctx.getBeansOfType(Step.class);
assertTrue("'s1' bean not found", beans.containsKey("s1"));
Step s1 = (Step) ctx.getBean("s1");
CompletionPolicy completionPolicy = getCompletionPolicy(s1);
assertTrue(completionPolicy instanceof SimpleCompletionPolicy);
assertEquals(25, ReflectionTestUtils.getField(completionPolicy, "chunkSize"));
}
@Test
@SuppressWarnings("resource")
public void testStepParserCompletionPolicy() throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserCompletionPolicyTests-context.xml");
Map<String, Step> beans = ctx.getBeansOfType(Step.class);
assertTrue("'s1' bean not found", beans.containsKey("s1"));
Step s1 = (Step) ctx.getBean("s1");
CompletionPolicy completionPolicy = getCompletionPolicy(s1);
assertTrue(completionPolicy instanceof DummyCompletionPolicy);
}
private CompletionPolicy getCompletionPolicy(Step s1) throws NoSuchFieldException, IllegalAccessException {
Object tasklet = ReflectionTestUtils.getField(s1, "tasklet");
Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider");
Object repeatOperations = ReflectionTestUtils.getField(chunkProvider, "repeatOperations");
return (CompletionPolicy) ReflectionTestUtils.getField(repeatOperations, "completionPolicy");
}
@Test(expected = BeanDefinitionParsingException.class)
@SuppressWarnings("resource")
public void testStepParserNoCommitIntervalOrCompletionPolicy() throws Exception {
new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserNoCommitIntervalOrCompletionPolicyTests-context.xml");
}
@Test(expected = BeanDefinitionParsingException.class)
@SuppressWarnings("resource")
public void testTaskletStepWithBadStepListener() throws Exception {
new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserBadStepListenerTests-context.xml");
}
@Test(expected = BeanDefinitionParsingException.class)
@SuppressWarnings("resource")
public void testTaskletStepWithBadRetryListener() throws Exception {
new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/StepParserBadRetryListenerTests-context.xml");
}
@Test
public void testParentStep() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
// Inline Step
assertTrue(getListener("s1", ctx) instanceof StepExecutionListenerSupport);
// Standalone Step
assertTrue(getListener("s2", ctx) instanceof StepExecutionListenerSupport);
// Inline With Tasklet Attribute Step
assertTrue(getListener("s3", ctx) instanceof StepExecutionListenerSupport);
// Standalone With Tasklet Attribute Step
assertTrue(getListener("s4", ctx) instanceof StepExecutionListenerSupport);
}
@Test
public void testInheritTransactionAttributes() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
// On Inline - No Merge
validateTransactionAttributesInherited("s1", ctx);
// On Standalone - No Merge
validateTransactionAttributesInherited("s2", ctx);
// On Inline With Tasklet Ref - No Merge
validateTransactionAttributesInherited("s3", ctx);
// On Standalone With Tasklet Ref - No Merge
validateTransactionAttributesInherited("s4", ctx);
// On Inline
validateTransactionAttributesInherited("s5", ctx);
// On Standalone
validateTransactionAttributesInherited("s6", ctx);
// On Inline With Tasklet Ref
validateTransactionAttributesInherited("s7", ctx);
// On Standalone With Tasklet Ref
validateTransactionAttributesInherited("s8", ctx);
}
private void validateTransactionAttributesInherited(String stepName, ApplicationContext ctx) {
DefaultTransactionAttribute txa = getTransactionAttribute(ctx, stepName);
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, txa.getPropagationBehavior());
assertEquals(TransactionDefinition.ISOLATION_DEFAULT, txa.getIsolationLevel());
assertEquals(10, txa.getTimeout());
}
@SuppressWarnings("unchecked")
private List<StepExecutionListener> getListeners(String stepName, ApplicationContext ctx) throws Exception {
assertTrue(ctx.containsBean(stepName));
Step step = (Step) ctx.getBean(stepName);
assertTrue(step instanceof TaskletStep);
Object compositeListener = ReflectionTestUtils.getField(step, "stepExecutionListener");
Object composite = ReflectionTestUtils.getField(compositeListener, "list");
List<StepExecutionListener> list = (List<StepExecutionListener>) ReflectionTestUtils
.getField(composite, "list");
List<StepExecutionListener> unwrappedList = new ArrayList<StepExecutionListener>();
for (StepExecutionListener listener : list) {
while (listener instanceof Advised) {
listener = (StepExecutionListener) ((Advised) listener).getTargetSource().getTarget();
}
unwrappedList.add(listener);
}
return unwrappedList;
}
private StepExecutionListener getListener(String stepName, ApplicationContext ctx) throws Exception {
List<StepExecutionListener> list = getListeners(stepName, ctx);
assertEquals(1, list.size());
return list.get(0);
}
private DefaultTransactionAttribute getTransactionAttribute(ApplicationContext ctx, String stepName) {
assertTrue(ctx.containsBean(stepName));
Step step = (Step) ctx.getBean(stepName);
assertTrue(step instanceof TaskletStep);
Object transactionAttribute = ReflectionTestUtils.getField(step, "transactionAttribute");
return (DefaultTransactionAttribute) transactionAttribute;
}
@Test
public void testInheritFromBean() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(getTasklet("s9", ctx) instanceof DummyTasklet);
assertTrue(getTasklet("s10", ctx) instanceof DummyTasklet);
}
private Tasklet getTasklet(String stepName, ApplicationContext ctx) {
assertTrue(ctx.containsBean(stepName));
Step step = (Step) ctx.getBean(stepName);
assertTrue(step instanceof TaskletStep);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
assertTrue(tasklet instanceof Tasklet);
return (Tasklet) tasklet;
}
@Test
public void testJobRepositoryDefaults() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(getJobRepository("defaultRepoStep", ctx) instanceof SimpleJobRepository);
assertTrue(getJobRepository("defaultRepoStepWithParent", ctx) instanceof SimpleJobRepository);
assertTrue(getJobRepository("overrideRepoStep", ctx) instanceof SimpleJobRepository);
assertDummyJobRepository("injectedRepoStep", "dummyJobRepository", ctx);
assertDummyJobRepository("injectedRepoStepWithParent", "dummyJobRepository", ctx);
assertDummyJobRepository("injectedOverrideRepoStep", "dummyJobRepository", ctx);
assertDummyJobRepository("injectedRepoFromParentStep", "dummyJobRepository2", ctx);
assertDummyJobRepository("injectedRepoFromParentStepWithParent", "dummyJobRepository2", ctx);
assertDummyJobRepository("injectedOverrideRepoFromParentStep", "dummyJobRepository2", ctx);
assertTrue(getJobRepository("defaultRepoStandaloneStep", ctx) instanceof SimpleJobRepository);
assertDummyJobRepository("specifiedRepoStandaloneStep", "dummyJobRepository2", ctx);
}
@Test
public void testTransactionManagerDefaults() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(getTransactionManager("defaultTxMgrStep", ctx) instanceof ResourcelessTransactionManager);
assertDummyTransactionManager("specifiedTxMgrStep", "dummyTxMgr", ctx);
assertDummyTransactionManager("defaultTxMgrWithParentStep", "dummyTxMgr", ctx);
assertDummyTransactionManager("overrideTxMgrOnParentStep", "dummyTxMgr2", ctx);
}
private void assertDummyJobRepository(String beanName, String jobRepoName, ApplicationContext ctx) throws Exception {
JobRepository jobRepository = getJobRepository(beanName, ctx);
assertTrue(jobRepository instanceof DummyJobRepository);
assertEquals(jobRepoName, ((DummyJobRepository) jobRepository).getName());
}
private void assertDummyTransactionManager(String beanName, String txMgrName, ApplicationContext ctx)
throws Exception {
PlatformTransactionManager txMgr = getTransactionManager(beanName, ctx);
assertTrue(txMgr instanceof DummyPlatformTransactionManager);
assertEquals(txMgrName, ((DummyPlatformTransactionManager) txMgr).getName());
}
private JobRepository getJobRepository(String beanName, ApplicationContext ctx) throws Exception {
Object jobRepository = getFieldFromBean(beanName, "jobRepository", ctx);
assertTrue(jobRepository instanceof JobRepository);
return (JobRepository) jobRepository;
}
private PlatformTransactionManager getTransactionManager(String beanName, ApplicationContext ctx) throws Exception {
Object jobRepository = getFieldFromBean(beanName, "transactionManager", ctx);
assertTrue(jobRepository instanceof PlatformTransactionManager);
return (PlatformTransactionManager) jobRepository;
}
private Object getFieldFromBean(String beanName, String field, ApplicationContext ctx) throws Exception {
assertTrue(ctx.containsBean(beanName));
Object bean = ctx.getBean(beanName);
assertTrue(bean instanceof AbstractStep || bean instanceof AbstractJob);
Object property = ReflectionTestUtils.getField(bean, field);
while (property instanceof Advised) {
property = ((Advised) property).getTargetSource().getTarget();
}
return property;
}
@Test
public void testNonAbstractStep() {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(ctx.containsBean("s11"));
Object bean = ctx.getBean("s11");
assertTrue(bean instanceof DummyStep);
}
@Test
public void testInlineTaskletElementOverridesParentBeanClass() {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(ctx.containsBean("&s12"));
Object factoryBean = ctx.getBean("&s12");
assertTrue(factoryBean instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("dummyStep"));
Object dummyStep = ctx.getBean("dummyStep");
assertTrue(dummyStep instanceof DummyStep);
assertTrue(ctx.containsBean("s12"));
Object bean = ctx.getBean("s12");
assertTrue(bean instanceof TaskletStep);
}
@Test
public void testTaskletElementOverridesChildBeanClass() {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(ctx.containsBean("&s13"));
Object factoryBean = ctx.getBean("&s13");
assertTrue(factoryBean instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("s13"));
Object bean = ctx.getBean("s13");
assertTrue(bean instanceof TaskletStep);
assertTrue(ctx.containsBean("&dummyStepWithTaskletOnParent"));
Object dummyStepFb = ctx.getBean("&dummyStepWithTaskletOnParent");
assertTrue(dummyStepFb instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("dummyStepWithTaskletOnParent"));
Object dummyStep = ctx.getBean("dummyStepWithTaskletOnParent");
assertTrue(dummyStep instanceof TaskletStep);
assertTrue(ctx.containsBean("&standaloneStepWithTasklet"));
Object standaloneStepFb = ctx.getBean("&standaloneStepWithTasklet");
assertTrue(standaloneStepFb instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("standaloneStepWithTasklet"));
Object standaloneStep = ctx.getBean("standaloneStepWithTasklet");
assertTrue(standaloneStep instanceof TaskletStep);
}
@Test
public void testTaskletElementOverridesParentBeanClass() {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
assertTrue(ctx.containsBean("&s14"));
Object factoryBean = ctx.getBean("&s14");
assertTrue(factoryBean instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("s12"));
Object bean = ctx.getBean("s12");
assertTrue(bean instanceof TaskletStep);
assertTrue(ctx.containsBean("&standaloneStepWithTaskletAndDummyParent"));
Object standaloneWithTaskletFb = ctx.getBean("&standaloneStepWithTaskletAndDummyParent");
assertTrue(standaloneWithTaskletFb instanceof StepParserStepFactoryBean<?,?>);
assertTrue(ctx.containsBean("standaloneStepWithTaskletAndDummyParent"));
Object standaloneWithTasklet = ctx.getBean("standaloneStepWithTaskletAndDummyParent");
assertTrue(standaloneWithTasklet instanceof TaskletStep);
assertTrue(ctx.containsBean("dummyStep"));
Object dummyStep = ctx.getBean("dummyStep");
assertTrue(dummyStep instanceof DummyStep);
}
@SuppressWarnings("unchecked")
@Test
public void testStepWithListsMerge() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
Map<Class<? extends Throwable>, Boolean> skippable = new HashMap<Class<? extends Throwable>, Boolean>();
skippable.put(SkippableRuntimeException.class, true);
skippable.put(SkippableException.class, true);
skippable.put(FatalRuntimeException.class, false);
skippable.put(FatalSkippableException.class, false);
skippable.put(ForceRollbackForWriteSkipException.class, true);
Map<Class<? extends Throwable>, Boolean> retryable = new HashMap<Class<? extends Throwable>, Boolean>();
retryable.put(DeadlockLoserDataAccessException.class, true);
retryable.put(FatalSkippableException.class, true);
retryable.put(ForceRollbackForWriteSkipException.class, true);
List<Class<? extends ItemStream>> streams = Arrays.asList(CompositeItemStream.class, TestReader.class);
List<Class<? extends RetryListener>> retryListeners = Arrays.asList(RetryListenerSupport.class,
DummyRetryListener.class);
List<Class<? extends StepExecutionListener>> stepListeners = Arrays.asList(StepExecutionListenerSupport.class,
CompositeStepExecutionListener.class);
List<Class<? extends SkippableRuntimeException>> noRollback = Arrays.asList(FatalRuntimeException.class,
SkippableRuntimeException.class);
StepParserStepFactoryBean<?, ?> fb = (StepParserStepFactoryBean<?, ?>) ctx.getBean("&stepWithListsMerge");
Map<Class<? extends Throwable>, Boolean> skippableFound = getExceptionMap(fb, "skippableExceptionClasses");
Map<Class<? extends Throwable>, Boolean> retryableFound = getExceptionMap(fb, "retryableExceptionClasses");
ItemStream[] streamsFound = (ItemStream[]) ReflectionTestUtils.getField(fb, "streams");
RetryListener[] retryListenersFound = (RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners");
Set<StepExecutionListener> stepListenersFound = (Set<StepExecutionListener>) ReflectionTestUtils.getField(fb, "stepExecutionListeners");
Collection<Class<? extends Throwable>> noRollbackFound = getExceptionList(fb, "noRollbackExceptionClasses");
assertSameMaps(skippable, skippableFound);
assertSameMaps(retryable, retryableFound);
assertSameCollections(streams, toClassCollection(streamsFound));
assertSameCollections(retryListeners, toClassCollection(retryListenersFound));
assertSameCollections(stepListeners, toClassCollection(stepListenersFound));
assertSameCollections(noRollback, noRollbackFound);
}
@SuppressWarnings("unchecked")
@Test
public void testStepWithListsNoMerge() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
Map<Class<? extends Throwable>, Boolean> skippable = new HashMap<Class<? extends Throwable>, Boolean>();
skippable.put(SkippableException.class, true);
skippable.put(FatalSkippableException.class, false);
skippable.put(ForceRollbackForWriteSkipException.class, true);
Map<Class<? extends Throwable>, Boolean> retryable = new HashMap<Class<? extends Throwable>, Boolean>();
retryable.put(FatalSkippableException.class, true);
retryable.put(ForceRollbackForWriteSkipException.class, true);
List<Class<CompositeItemStream>> streams = Arrays.asList(CompositeItemStream.class);
List<Class<DummyRetryListener>> retryListeners = Arrays.asList(DummyRetryListener.class);
List<Class<CompositeStepExecutionListener>> stepListeners = Arrays.asList(CompositeStepExecutionListener.class);
List<Class<SkippableRuntimeException>> noRollback = Arrays.asList(SkippableRuntimeException.class);
StepParserStepFactoryBean<?, ?> fb = (StepParserStepFactoryBean<?, ?>) ctx.getBean("&stepWithListsNoMerge");
Map<Class<? extends Throwable>, Boolean> skippableFound = getExceptionMap(fb, "skippableExceptionClasses");
Map<Class<? extends Throwable>, Boolean> retryableFound = getExceptionMap(fb, "retryableExceptionClasses");
ItemStream[] streamsFound = (ItemStream[]) ReflectionTestUtils.getField(fb, "streams");
RetryListener[] retryListenersFound = (RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners");
Set<StepExecutionListener> stepListenersFound = (Set<StepExecutionListener>) ReflectionTestUtils.getField(fb, "stepExecutionListeners");
Collection<Class<? extends Throwable>> noRollbackFound = getExceptionList(fb, "noRollbackExceptionClasses");
assertSameMaps(skippable, skippableFound);
assertSameMaps(retryable, retryableFound);
assertSameCollections(streams, toClassCollection(streamsFound));
assertSameCollections(retryListeners, toClassCollection(retryListenersFound));
assertSameCollections(stepListeners, toClassCollection(stepListenersFound));
assertSameCollections(noRollback, noRollbackFound);
}
@SuppressWarnings("unchecked")
@Test
public void testStepWithListsOverrideWithEmpty() throws Exception {
ApplicationContext ctx = stepParserParentAttributeTestsCtx;
StepParserStepFactoryBean<?, ?> fb = (StepParserStepFactoryBean<?, ?>) ctx
.getBean("&stepWithListsOverrideWithEmpty");
assertEquals(1, getExceptionMap(fb, "skippableExceptionClasses").size());
assertEquals(1, getExceptionMap(fb, "retryableExceptionClasses").size());
assertEquals(0, ((ItemStream[]) ReflectionTestUtils.getField(fb, "streams")).length);
assertEquals(0, ((RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners")).length);
assertEquals(0, ((Set<StepExecutionListener>) ReflectionTestUtils.getField(fb, "stepExecutionListeners")).size());
assertEquals(0, getExceptionList(fb, "noRollbackExceptionClasses").size());
}
@SuppressWarnings("unchecked")
private Collection<Class<? extends Throwable>> getExceptionList(StepParserStepFactoryBean<?, ?> fb,
String propertyName) {
return (Collection<Class<? extends Throwable>>) ReflectionTestUtils.getField(fb, propertyName);
}
@SuppressWarnings("unchecked")
private Map<Class<? extends Throwable>, Boolean> getExceptionMap(StepParserStepFactoryBean<?, ?> fb,
String propertyName) {
return (Map<Class<? extends Throwable>, Boolean>) ReflectionTestUtils.getField(fb, propertyName);
}
private <T, S extends T> void assertSameCollections(Collection<S> expected, Collection<T> actual) {
assertEquals(expected.size(), actual.size());
assertTrue(expected.containsAll(actual));
}
private <T, S> void assertSameMaps(Map<T, S> expected, Map<T, S> actual) {
assertEquals(expected.size(), actual.size());
for (Entry<T, S> e : expected.entrySet()) {
assertTrue(actual.containsKey(e.getKey()));
assertEquals(e.getValue(), actual.get(e.getKey()));
}
}
private <T> Collection<Class<? extends T>> toClassCollection(T[] in) throws Exception {
return toClassCollection(Arrays.asList(in));
}
@SuppressWarnings("unchecked")
private <T> Collection<Class<? extends T>> toClassCollection(Collection<T> in) throws Exception {
Collection<Class<? extends T>> out = new ArrayList<Class<? extends T>>();
for (T item : in) {
while (item instanceof Advised) {
item = (T) ((Advised) item).getTargetSource().getTarget();
}
Class<? extends T> cls = (Class<? extends T>) item.getClass();
out.add(cls);
}
return out;
}
}