ItemReader integration testing throwing ClassCastException

旧时模样 提交于 2019-12-08 14:22:09

问题


I am trying to integration test an ItemReader - here is the class:

@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();
  }

Here is my bean.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>

And here is the test I'm trying to write:

@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
    }
}

I am getting java.lang.ClassCastException: com.sun.proxy.$Proxy36 cannot be cast to ItemReader on the Before and After. What am I missing? Is there anything else I need to setup for this (e.g. any annotations or entry in the config xml)?


回答1:


Your problem is an ItemReader is not an ItemStream. your StudioReader need implementes org.springframework.batch.item.ItemStreamReader if you want use a reader as a stream.

import org.springframework.batch.item.ItemStreamReader;

public class StudioReader implements ItemStreamReader<List<Studio>>{
   ...
}

you can use Generic type to make the type T as multiple interfaces to avoid cast expression in @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(); 
   }

}

Test

@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));
        }
    }
}



回答2:


When using a combination of XML config and Java config with Spring Batch, you end up with some confusion on how to create the proxy for step scoped beans. Change the configuration of your step scope to the following:

<bean class="org.springframework.batch.core.scope.StepScope">
    <property name="proxyTargetClass" value="true"/>
</bean>


来源:https://stackoverflow.com/questions/43197700/itemreader-integration-testing-throwing-classcastexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!