我正在尝试为Spring Batch应用程序编写tests,特别是关于以下reader的交互,当它从实现简单RowMapper的数据库中获取记录时:
@Component
@StepScope
public class RecordItemReader extends JdbcCursorItemReader<FooDto> {
@Autowired
public RecordItemReader(DataSource dataSource) {
this.setDataSource(dataSource);
this.setSql(AN_SQL_QUERY);
this.setRowMapper(new RecordItemMapper());
}
}
这是批处理配置中的步骤定义:
@Bean
public Step step(RecordItemReader recordItemReader,
BatchSkipListener skipListener,
RecordItemWriter writer,
RecordItemProcessor processor,
PlatformTransactionManager transactionManager) {
return stepBuilderFactory
.get("step1")
.transactionManager(transactionManager)
.reader(recordItemReader)
.faultTolerant()
.skip(ParseException.class)
.skip(UnexpectedInputException.class)
.skipPolicy(new AlwaysSkipItemSkipPolicy())
.listener(skipListener)
.processor(processor)
.writer(writer)
.build();
}
一切正常,除非我尝试使用以下方法进行测试:
@SpringBatchTest
@EnableAutoConfiguration
class BatchSOTest extends Specification {
@Resource
JobLauncherTestUtils jobLauncherTestUtils
@Resource
JobRepositoryTestUtils jobRepositoryTestUtils
@Resource
RecordItemReader recordItemReader
def cleanup() {
jobRepositoryTestUtils.removeJobExecutions()
}
def "batch init perfectly"() {
given:
// this does not work :
(1.._) * recordItemReader.read() >> null
when:
def jobExecution = jobLauncherTestUtils.launchJob()
def jobInstance = jobExecution.getJobInstance()
def exitStatus = jobExecution.getExitStatus()
then:
jobInstance.getJobName() == "soJob"
exitStatus.getExitCode() == ExitStatus.SUCCESS.getExitCode()
}
}
我无法正确模拟读者,我尝试了多种方法,例如更新读者的属性,例如MaxRows
,但似乎无济于事。
什么是更新阅读器结果的正确方法?>
或者是否需要采取另一种方式从数据库在单元测试期间]正确地处理记录?]
UPDATE:好的,所以我尝试了使用阅读器内部的服务进行更结构化的方法:
@Component
public class FooDtoItemReader extends AbstractItemStreamItemReader<FooDto> {
private List<FooDto> foos ;
private final FooService fooService;
@Autowired
public FooDtoItemReader(FooService fooService) {
this.fooService = fooService;
}
@Override
public void open(ExecutionContext executionContext) {
try {
foos = fooService.getFoos();
...
public interface FooService {
List<FooDto> getFoos();
}
@Service
public class FooServiceImpl implements FooService {
@Autowired
private FooDao fooDao;
@Override
public List<FooDto> getFoos() {
return fooDao.getFoos();
}
}
@Repository
public class FooDaoImpl extends JdbcDaoSupport implements FooDao {
@Autowired
DataSource dataSource;
@PostConstruct
private void initialize() {
setDataSource(dataSource);
}
@Override
public List<FooDto> getFoos() {
return getJdbcTemplate().query(SELECT_SQL, new FooMapper());
}
}
[这里,我遇到的问题是我无法正确模拟服务:
我必须在测试实用程序中缺少一些东西。
class BatchSOTest extends Specification {
@Resource
JobLauncherTestUtils jobLauncherTestUtils
@Resource
JobRepositoryTestUtils jobRepositoryTestUtils
FooService fooService = Mock(FooService);
FooDtoItemReader fooDtoItemReader = new FooDtoItemReader(fooService)
def cleanup() {
jobRepositoryTestUtils.removeJobExecutions()
}
def "batch init perfectly (second version)"() {
given:
fooDtoItemReader.open(Mock(ExecutionContext))
and:
// still not working from there :
(1.._) * fooService.getFoos() >> [createFooEntity(123, "Test")]
when:
def jobExecution = jobLauncherTestUtils.launchJob()
def jobInstance = jobExecution.getJobInstance()
def exitStatus = jobExecution.getExitStatus()
then:
jobInstance.getJobName() == "soJob"
exitStatus.getExitCode() == ExitStatus.SUCCESS.getExitCode()
}
但是,如果我尝试从那里嘲笑,那是可行的:
class FooDtoItemReaderTest extends Specification {
FooService fooService = Mock(FooService);
FooDtoItemReader fooDtoItemReader = new FooDtoItemReader(fooService, 0)
def "open gets the foos and reader is initialized"() {
given: "Foos examples"
def foos = [
createFooEntity(123, "A"),
createFooEntity(456, "B")
]
when: "reader is initialized"
fooDtoItemReader.open(Mock(ExecutionContext))
then: "service get the expected foos"
1 * fooService.getFoos() >> foos
}
所以我做错了什么?
我正在尝试为Spring Batch应用程序编写测试,尤其是以下读者在从实现简单RowMapper的数据库中获取记录时与以下读者的交互:@ ...] >> [[
关于测试数据库交互,我不会嘲笑读者。相反,我将使用嵌入式数据库并用测试数据填充它。这可以通过将以下bean添加到您的测试上下文中来实现:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("/org/springframework/batch/core/schema-drop-h2.sql")
.addScript("/org/springframework/batch/core/schema-h2.sql")
.addScript("/schema.sql")
.addScript("/test-data.sql")
.build();
}
此示例使用H2,但是您可以使用derby或HSLQ或SQLite或任何其他可嵌入的数据库。