JUnit test for a Step scoped Bean using StepScopeTestExecutionListener.class : Still getting "No Scope registered"

huangapple go评论77阅读模式
英文:

JUnit test for a Step scoped Bean using StepScopeTestExecutionListener.class : Still getting "No Scope registered"

问题

我正试图为一个“步骤”作用域的bean编写独立的单元测试用例。我之前在这里发布了这个问题,并且了解到我需要使用StepScopeTestExecutionListener为我的单元测试创建一个步骤作用域;然而,即使在使用了StepScopeTestExecutionListener之后,我仍然会收到以下异常:

Caused by: java.lang.IllegalStateException: No Scope registered for scope name 'step'
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:343)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

我的JUnit测试

@TestExecutionListeners({ StepScopeTestExecutionListener.class,DependencyInjectionTestExecutionListener.class  })
@RunWith(SpringJUnit4ClassRunner.class)
@PropertySource("classpath:properties/common.properties")
@ContextConfiguration(locations = { "/spring/common-context.xml" })
public class ConfigDAOImplTest {

    @Autowired
    private ConfigDAOImpl configDAO;

    @Spy
    private ContextParamDAO contextParamDAO = new ContextParamDAOImpl();

    private static final String SCHEMA_CONFIG = "classpath:data/CONFIG_SCHEMA.sql";
    private static final String DATA_CONFIG = "classpath:data/CONFIG_DATA.sql";

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);

        DataSource dataSource = new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript(SCHEMA_CONFIG)
                .addScript(DATA_CONFIG)
                .build();

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        //override the jdbcTemplate for the test case    
        configDAO.setJdbcTemplate(jdbcTemplate);
        configDAO.setContextParamDAO(contextParamDAO);
    }

    public StepExecution getStepExecution() {

		JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
		jobParametersBuilder.addString("test", "test");
		JobParameters jobParameters = jobParametersBuilder.toJobParameters();
		
		JobInstance jobInstance = new JobInstance(12345L,"testJob");
		JobExecution jobExecution = new JobExecution(jobInstance,jobParameters);

		StepExecution execution = 
        MetaDataInstanceFactory.createStepExecution(jobExecution,"step",11245L);
		execution.getExecutionContext().putString("input.data", "foo,bar,spam");
		return execution;
	}
}

我可以确认getStepExecution确实被调用了,因为我在这个方法上设置了断点,然后以调试模式运行了单元测试。

问题:为什么步骤作用域仍然没有初始化我的JUnit?

**注意:**无关的是,我在getStepExecution内部手动创建JobExecution,而不是使用MetaDataInstanceFactory.createJobExecution的原因是,出于一些奇怪的原因,编译器能够找到createJobExecution方法,但在运行时找不到该方法。我使用了-verbose:class标志,可以确认只有一个包含MetaDataInstanceFactory类的jar被加载,而且该jar也包含所需的方法。我假设手动创建JobExecution实例不应该是我的问题的根本原因。

英文:

I am trying to write an independent unit test case for a "step" scoped bean. I posted this question earlier and understand that I need to use a StepScopeTestExecutionListener to create a step scope for my unit test; however, I still get the following exception even after using the StepScopeTestExecutionListener :

Caused by: java.lang.IllegalStateException: No Scope registered for scope name 'step'
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:343)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

My JUnt

@TestExecutionListeners({ StepScopeTestExecutionListener.class,DependencyInjectionTestExecutionListener.class  })
@RunWith(SpringJUnit4ClassRunner.class)
@PropertySource("classpath:properties/common.properties")
@ContextConfiguration(locations = { "/spring/common-context.xml" })
public class ConfigDAOImplTest {

    @Autowired
    private ConfigDAOImpl configDAO;

    @Spy
    private ContextParamDAO contextParamDAO = new ContextParamDAOImpl();

    private static final String SCHEMA_CONFIG = "classpath:data/CONFIG_SCHEMA.sql";
    private static final String DATA_CONFIG = "classpath:data/CONFIG_DATA.sql";

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);

        DataSource dataSource = new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript(SCHEMA_CONFIG)
                .addScript(DATA_CONFIG)
                .build();

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        //override the jdbcTemplate for the test case    
        configDAO.setJdbcTemplate(jdbcTemplate);
        configDAO.setContextParamDAO(contextParamDAO);


    }

    public StepExecution getStepExecution() {

		JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
		jobParametersBuilder.addString("test", "test");
		JobParameters jobParameters = jobParametersBuilder.toJobParameters();
		
		JobInstance jobInstance = new JobInstance(12345L,"testJob");
		JobExecution jobExecution = new JobExecution(jobInstance,jobParameters);

		StepExecution execution = 
        MetaDataInstanceFactory.createStepExecution(jobExecution,"step",11245L);
		execution.getExecutionContext().putString("input.data", "foo,bar,spam");
		return execution;
	}
}

I can confirm that the getStepExecution does get called as I ran the unit test in debug mode with a breakpoint on this method.

Question : Why is the step scope still not getting initialized for my JUnit?

Note: On an unrelated note, the reason why I am manually creating a JobExecution inside getStepExecution instead of using MetaDataInstanceFactory.createJobExecution is because for some weird reason, the compiler is able to find the createJobExecution method but the method is not found at runtime. I used the -verbose:class flag and can confirm that there is only one jar from where the MetaDataInstanceFactory class gets loaded and that jar contains the required method as well. I am assuming that manually creating a JobExecution instance should not be the root cause of my issue.

答案1

得分: 3

错误发生在甚至加载您的测试之前,因为在您的common-context.xml文件中没有定义步骤范围的 bean。由于您在该文件中没有使用批处理命名空间,您需要手动声明步骤范围。以下摘录来自文档(版本为3.0.10):

因为它默认不是 Spring 容器的一部分,作用域必须显式地添加,
可以通过使用批处理命名空间或者为 StepScope 显式地包含一个 bean 定义来实现(但不能同时使用两者)。

将以下内容添加到您的应用程序上下文中应该可以解决问题:

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

The error happens before even loading your test, since there is no step scope bean defined in your common-context.xml file. Since you are not using the batch namespace in that file, you need to declare the step scope manually. Here is an excerpt from the docs (of 3.0.10):

Because it is not part of the Spring container by default, 
the scope must be added explicitly, either by using the batch namespace
or by including a bean definition explicitly for the StepScope (but not both)

Adding the following to your application context should fix the issue:

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

huangapple
  • 本文由 发表于 2020年4月9日 13:39:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/61114625.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定