抛出ClassCastException

时间:2017-04-04 03:26:34

标签: spring-boot java-8 integration-testing spring-batch

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

这是我的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>

这是我试图写的测试:

@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。$ Proxy36无法在Before和After上强制转换为ItemReader。我错过了什么?还有什么我需要为此设置(例如,配置xml中的任何注释或条目)?

2 个答案:

答案 0 :(得分:1)

您的问题是ItemReader不是ItemStream。如果您想将阅读器用作流,则StudioReader需要实施org.springframework.batch.item.ItemStreamReader

import org.springframework.batch.item.ItemStreamReader;

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

您可以使用Generic类型将类型T设置为多个接口,以避免在@Before&amp; @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));
        }
    }
}

答案 1 :(得分:0)

将XML配置和Java配置与Spring Batch结合使用时,最终会对如何为步骤范围bean创建代理产生一些困惑。将步骤范围的配置更改为以下内容:

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