英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论