ItemReader 集成测试抛出 ClassCastException



我正在尝试集成测试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>

最新更新