diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java new file mode 100644 index 000000000..a8fd20c1e --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java @@ -0,0 +1,67 @@ +package org.springframework.batch.item; + +import org.springframework.batch.item.sample.Foo; +import org.springframework.util.Assert; + +import junit.framework.TestCase; + +/** + * Common tests for {@link ItemReader} implementations. Expected input is five + * {@link Foo} objects with values 1 to 5. + */ +public abstract class CommonItemReaderTests extends TestCase { + + protected ItemReader tested; + + /** + * @return configured ItemReader ready for use. + */ + protected abstract ItemReader getItemReader() throws Exception; + + protected void setUp() throws Exception { + tested = getItemReader(); + } + + /** + * Regular scenario - read the input and eventually return null. + */ + public void testRead() throws Exception { + + Foo foo1 = (Foo) tested.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) tested.read(); + assertEquals(2, foo2.getValue()); + + Foo foo3 = (Foo) tested.read(); + assertEquals(3, foo3.getValue()); + + Foo foo4 = (Foo) tested.read(); + assertEquals(4, foo4.getValue()); + + Foo foo5 = (Foo) tested.read(); + assertEquals(5, foo5.getValue()); + + assertNull(tested.read()); + } + + /** + * Rollback scenario - reader resets to last marked point. + */ + public void testReset() throws Exception { + Foo foo1 = (Foo) tested.read(); + + tested.mark(); + + Foo foo2 = (Foo) tested.read(); + Assert.state(!foo2.equals(foo1)); + + Foo foo3 = (Foo) tested.read(); + Assert.state(!foo2.equals(foo3)); + + tested.reset(); + + assertEquals(foo2, tested.read()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemStreamItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemStreamItemReaderTests.java new file mode 100644 index 000000000..7d018fbe8 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemStreamItemReaderTests.java @@ -0,0 +1,57 @@ +package org.springframework.batch.item; + +import org.springframework.batch.item.sample.Foo; + +/** + * Common tests for readers implementing both {@link ItemReader} and + * {@link ItemStream}. Expected input is five {@link Foo} objects with values 1 + * to 5. + */ +public abstract class CommonItemStreamItemReaderTests extends CommonItemReaderTests { + + protected ExecutionContext executionContext = new ExecutionContext(); + + /** + * Cast the reader to ItemStream. + */ + protected ItemStream testedAsStream() { + return (ItemStream) tested; + } + + protected void setUp() throws Exception { + super.setUp(); + testedAsStream().open(executionContext); + } + + protected void tearDown() throws Exception { + super.tearDown(); + testedAsStream().close(executionContext); + } + + + + /** + * Restart scenario - read items, update execution context, create new + * reader and restore from restart data - the new input source should + * continue where the old one finished. + */ + public void testRestart() throws Exception { + + Foo foo1 = (Foo) tested.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) tested.read(); + assertEquals(2, foo2.getValue()); + + testedAsStream().update(executionContext); + + // create new input source + tested = getItemReader(); + + testedAsStream().open(executionContext); + + Foo fooAfterRestart = (Foo) tested.read(); + assertEquals(3, fooAfterRestart.getValue()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/BatchSqlUpdateItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/BatchSqlUpdateItemWriterTests.java index d28666bee..7e2943c75 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/BatchSqlUpdateItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/BatchSqlUpdateItemWriterTests.java @@ -20,9 +20,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; -import java.util.Map; import junit.framework.TestCase; @@ -88,10 +86,8 @@ public class BatchSqlUpdateItemWriterTests extends TestCase { * @see junit.framework.TestCase#tearDown() */ protected void tearDown() throws Exception { - Map map = TransactionSynchronizationManager.getResourceMap(); - for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { - String key = (String) iterator.next(); - TransactionSynchronizationManager.unbindResource(key); + if (TransactionSynchronizationManager.hasResource(BatchSqlUpdateItemWriter.ITEMS_PROCESSED)) { + TransactionSynchronizationManager.unbindResource(BatchSqlUpdateItemWriter.ITEMS_PROCESSED); } RepeatSynchronizationManager.clear(); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CommonDatabaseItemStreamItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CommonDatabaseItemStreamItemReaderTests.java new file mode 100644 index 000000000..ae5380e2b --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CommonDatabaseItemStreamItemReaderTests.java @@ -0,0 +1,26 @@ +package org.springframework.batch.item.database; + +import javax.sql.DataSource; + +import org.springframework.batch.item.CommonItemStreamItemReaderTests; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public abstract class CommonDatabaseItemStreamItemReaderTests extends CommonItemStreamItemReaderTests { + + private ClassPathXmlApplicationContext ctx; + + protected void setUp() throws Exception { + ctx = new ClassPathXmlApplicationContext("foo-data-source-context.xml", JdbcCursorItemReaderCommonTests.class); + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + ctx.close(); + } + + protected DataSource getDataSource() { + return (DataSource) ctx.getBean("dataSource"); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java new file mode 100644 index 000000000..601e36ab0 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java @@ -0,0 +1,31 @@ +package org.springframework.batch.item.database; + +import org.hibernate.SessionFactory; +import org.springframework.batch.item.ItemReader; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.orm.hibernate3.LocalSessionFactoryBean; + +public class HibernateCursorItemReaderCommonTests extends CommonDatabaseItemStreamItemReaderTests { + + protected ItemReader getItemReader() throws Exception { + LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); + factoryBean.setDataSource(getDataSource()); + factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); + factoryBean.afterPropertiesSet(); + + SessionFactory sessionFactory = (SessionFactory) factoryBean.getObject(); + + String hsqlQuery = "from Foo"; + + HibernateCursorItemReader reader = new HibernateCursorItemReader(); + reader.setQueryString(hsqlQuery); + reader.setSessionFactory(sessionFactory); + reader.setUseStatelessSession(true); + reader.afterPropertiesSet(); + reader.setSaveState(true); + + return reader; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisItemReaderCommonTests.java new file mode 100644 index 000000000..cef6f6f29 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisItemReaderCommonTests.java @@ -0,0 +1,32 @@ +package org.springframework.batch.item.database; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.database.support.IbatisKeyCollector; +import org.springframework.core.io.ClassPathResource; +import org.springframework.orm.ibatis.SqlMapClientFactoryBean; + +import com.ibatis.sqlmap.client.SqlMapClient; + +public class IbatisItemReaderCommonTests extends CommonDatabaseItemStreamItemReaderTests { + + protected ItemReader getItemReader() throws Exception { + SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); + factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); + factory.setDataSource(getDataSource()); + factory.afterPropertiesSet(); + SqlMapClient sqlMapClient = (SqlMapClient) factory.getObject(); + + IbatisDrivingQueryItemReader reader = new IbatisDrivingQueryItemReader(); + IbatisKeyCollector keyGenerator = new IbatisKeyCollector(); + keyGenerator.setDrivingQueryId("getAllFooIds"); + reader.setDetailsQueryId("getFooById"); + keyGenerator.setRestartQueryId("getAllFooIdsRestart"); + keyGenerator.setSqlMapClient(sqlMapClient); + reader.setSqlMapClient(sqlMapClient); + reader.setKeyCollector(keyGenerator); + reader.setSaveState(true); + + return reader; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java new file mode 100644 index 000000000..acd9ce86d --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java @@ -0,0 +1,24 @@ +package org.springframework.batch.item.database; + +import org.springframework.batch.item.ItemReader; + +public class JdbcCursorItemReaderCommonTests extends CommonDatabaseItemStreamItemReaderTests { + + protected ItemReader getItemReader() throws Exception { + + JdbcCursorItemReader result = new JdbcCursorItemReader(); + result.setDataSource(getDataSource()); + result.setSql("select ID, NAME, VALUE from T_FOOS"); + result.setIgnoreWarnings(true); + result.setVerifyCursorPosition(true); + + result.setMapper(new FooRowMapper()); + result.setFetchSize(10); + result.setMaxRows(100); + result.setQueryTimeout(1000); + result.setSaveState(true); + + return result; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleColumnJdbcDrivingQueryItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleColumnJdbcDrivingQueryItemReaderCommonTests.java new file mode 100644 index 000000000..82315efb3 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleColumnJdbcDrivingQueryItemReaderCommonTests.java @@ -0,0 +1,20 @@ +package org.springframework.batch.item.database; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.database.support.SingleColumnJdbcKeyCollector; +import org.springframework.jdbc.core.JdbcTemplate; + +public class SingleColumnJdbcDrivingQueryItemReaderCommonTests extends CommonDatabaseItemStreamItemReaderTests { + + protected ItemReader getItemReader() throws Exception { + JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource()); + SingleColumnJdbcKeyCollector keyStrategy = new SingleColumnJdbcKeyCollector(jdbcTemplate, + "SELECT ID from T_FOOS order by ID"); + keyStrategy.setRestartSql("SELECT ID from T_FOOS where ID > ? order by ID"); + DrivingQueryItemReader reader = new DrivingQueryItemReader(); + reader.setKeyCollector(keyStrategy); + reader.setSaveState(true); + return new FooItemReader(reader, jdbcTemplate); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java new file mode 100644 index 000000000..4f2426b49 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java @@ -0,0 +1,32 @@ +package org.springframework.batch.item.file; + +import org.springframework.batch.item.CommonItemStreamItemReaderTests; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.file.mapping.FieldSet; +import org.springframework.batch.item.file.mapping.FieldSetMapper; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +public class FlatFileItemReaderCommonTests extends CommonItemStreamItemReaderTests { + + private final String FOOS = "1 \n 2 \n 3 \n 4 \n 5 \n"; + + protected ItemReader getItemReader() throws Exception { + FlatFileItemReader tested = new FlatFileItemReader(); + Resource resource = new ByteArrayResource(FOOS.getBytes()); + tested.setResource(resource); + tested.setFieldSetMapper(new FieldSetMapper() { + public Object mapLine(FieldSet fs) { + Foo foo = new Foo(); + foo.setValue(fs.readInt(0)); + return foo; + } + }); + + tested.setSaveState(true); + tested.afterPropertiesSet(); + return tested; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java new file mode 100644 index 000000000..6b8e70b77 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java @@ -0,0 +1,43 @@ +package org.springframework.batch.item.xml; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; + +import org.springframework.batch.item.CommonItemStreamItemReaderTests; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ByteArrayResource; + +public class StaxEventItemReaderCommonTests extends CommonItemStreamItemReaderTests { + + private final String FOOS = " "; + + protected ItemReader getItemReader() throws Exception { + StaxEventItemReader reader = new StaxEventItemReader(); + reader.setResource(new ByteArrayResource(FOOS.getBytes())); + reader.setFragmentRootElementName("foo"); + reader.setFragmentDeserializer(new EventReaderDeserializer() { + public Object deserializeFragment(XMLEventReader eventReader) { + Attribute attr; + try { + assertTrue(eventReader.nextEvent().isStartDocument()); + StartElement event = eventReader.nextEvent().asStartElement(); + attr = (Attribute) event.getAttributes().next(); + } + catch (XMLStreamException e) { + throw new RuntimeException(e); + } + Foo foo = new Foo(); + foo.setValue(Integer.parseInt(attr.getValue())); + return foo; + } + }); + + reader.setSaveState(true); + reader.afterPropertiesSet(); + return reader; + } + +} diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/foo-data-source-context.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/foo-data-source-context.xml new file mode 100644 index 000000000..0cb93caa3 --- /dev/null +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/foo-data-source-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file