我正在尝试集成测试ItemReader - 这是类:
@Slf4j
public class StudioReader implements ItemReader<List<Studio>> {
@Setter private zoneDao zoneDao;
@Getter @Setter private BatchContext context;
private AreaApi areaApi = new AreaApi();
public List<Studio> read() throws Exception {
return areaApi.getStudioLocations();
}
这是我的豆子.xml:
<bean class="org.springframework.batch.core.scope.StepScope" />
<bean id="ItemReader" class="com.sync.studio.reader.StudioReader" scope="step">
<property name="context" ref="BatchContext" />
<property name="zoneDao" ref="zoneDao" />
</bean>
这是我正在尝试编写的测试:
@ContextConfiguration(locations = {
"classpath:config/studio-beans.xml",
"classpath:config/test-context.xml"})
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
StepScopeTestExecutionListener.class })
public class StudioSyncReaderIT extends BaseTest {
@Autowired
private ItemReader<List<Studio>> reader;
public StepExecution getStepExecution() {
JobParameters jobParameters = new JobParametersBuilder()
.toJobParameters();
StepExecution execution = createStepExecution(
jobParameters);
return execution;
}
@Before
public void setUp() {
((ItemStream) reader).open(new ExecutionContext()); } //ClassCastException
@Test
@DirtiesContext
public void testReader() throws Exception {
assertNotNull(reader.read());
}
@After
public void tearDown() {
((ItemStream) reader).close(); //ClassCastException
}
}
我正在得到java.lang.ClassCastException:com.sun.proxy.$Proxy 36不能在之前和之后投射到ItemReader。我错过了什么?我还需要为此设置其他内容(例如,配置 xml 中的任何注释或条目(?
你的问题是ItemReader
不是ItemStream
. 如果你想使用阅读器作为流,你的StudioReader
需要实现org.springframework.batch.item.ItemStreamReader
。
import org.springframework.batch.item.ItemStreamReader;
public class StudioReader implements ItemStreamReader<List<Studio>>{
...
}
您可以使用 Generic type 使类型T
为多个接口,以避免在 @Before
& @After
中进行强制转换表达式。
public class StudioSyncReaderIT<T extends ItemReader<List<Studio>> & ItemStream >
extends BaseTest {
@Autowired
private T reader;
@Before
public void setUp() {
reader.open(new ExecutionContext());
}
@After
public void tearDown() {
reader.close();
}
}
测试
@ContextConfiguration
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class AutowireDependencyImplementedMultiInterfacesTest<T extends Supplier<List<String>> & Runnable & AutowireDependencyImplementedMultiInterfacesTest.Task> {
@Autowired
private T springTest;
@Test
public void inject() throws Throwable {
assertThat(springTest, is(not(instanceOf(MockTask.class))));
assertThat(springTest.get(), equalTo(singletonList("spring-test")));
springTest.hasBeenRan(false);
springTest.run();
springTest.hasBeenRan(true);
}
@Configuration
static class Config {
@Bean("step")
public StepScope stepScope() {
return new StepScope();
}
@Bean
@Scope(value = "step")
public MockTask task() {
return new MockTask("spring-test");
}
}
interface Task {
void hasBeenRan(boolean ran);
}
static class MockTask implements Supplier<List<String>>, Runnable, Task {
private final List<String> descriptions;
private boolean ran = false;
public MockTask(String... descriptions) {
this.descriptions = asList(descriptions);
}
@Override
public void run() {
ran = true;
}
@Override
public List<String> get() {
return descriptions;
}
public void hasBeenRan(boolean ran) {
assertThat(this.ran, is(ran));
}
}
}
XML config 和 Java config 与 Spring Batch 结合使用时,您最终会对如何为步骤范围的 bean 创建代理感到困惑。 将步骤范围的配置更改为以下内容:
<bean class="org.springframework.batch.core.scope.StepScope">
<property name="proxyTargetClass" value="true"/>
</bean>