【问题标题】:ItemReader integration testing throwing ClassCastExceptionItemReader 集成测试抛出 ClassCastException
【发布时间】:2017-08-29 02:11:18
【问题描述】:

我正在尝试集成测试 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 cannot be cast to ItemReader on the Before and After。我错过了什么?我还需要为此设置什么(例如,配置 xml 中的任何注释或条目)?

【问题讨论】:

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


    【解决方案1】:

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

    import org.springframework.batch.item.ItemStreamReader;
    
    public class StudioReader implements ItemStreamReader<List<Studio>>{
       ...
    }
    

    您可以使用泛型类型将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));
            }
        }
    }
    

    【讨论】:

    • 不确定第二部分在做什么?您是说这是解决问题的两种方法吗?同样在第一部分,您建议测试类扩展 ItemReaders?
    • @Yana 我已将 junit-5 转换为 junit4。带有通用参数T 的测试类不扩展ItemReader
    • 我得到 - 无法自动装配 - 找不到 T 类型的 bean!
    • @Yana 因为你的StudioReader 不是ItemStream
    【解决方案2】:

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

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

    【讨论】:

    • 它说找不到 proxyTargetClass - 我在哪里以及如何声明它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多