Spring JUnit 测试:自动装配和事务问题
我们有一个现有的 Java EE 应用程序,它利用 Spring 并正在从 xml 配置过渡到自动装配。我们刚刚将大部分 EJB 转换为 Spring bean,但目前仍然使用 MDB 和 EJB 计时器。
- WAS 7.0
- Java 6
- Spring 3.0.5
- JUnit 4.8.1
我也在 JUnit 中编写集成测试。我的集成测试使用大多数上下文配置文件,就像在 WAS 中运行时一样,但不使用与 JNDI 相关的内容或使用 JTA 事务管理器。对于这些,我有设置 ActiveMQ 队列、Hibernate 事务管理器等的等效项。
我的测试如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/junit-container-context.xml",
"/spring-contexts/service-context.xml",
"/spring-contexts/integration-context.xml",
"/available-tests-context.xml" })
public class TestCase1Runner {
@Autowired
TestCase1 test;
@Autowired
private ApplicationContext applicationContext;
@Before
public void setupErrorHandling() {
// Some setup
}
@Test
@Transactional
public void run() throws Exception {
test.executeTest();
}
}
我的测试至少由于以下几个原因而出现问题:
- 自动装配会跳过一些 bean
- 有时 bean 不会代理事务
Item 1似乎与循环引用有关。我复制了一些有自动装配问题的 Bean。我在同一个包裹中制作了副本。副本已连接,但原件未连接。然后,我开始将 xml 上下文文件中的引用从原始文件移动到副本,在某些时候,副本不再连接,但原始文件却连接。我在其中一个上下文文件中有以下内容(为了保护我而更改了名称:):
<context:component-scan
base-package="com.mycompany.package1,com.mycompany.package2" />
<context:annotation-config />
我认为第二个实体是多余的,但应该是无害的。
我在日志中没有看到任何错误。我将日志记录转为调试,并看到大多数 bean 都被自动装配,但 Spring 似乎没有跳过任何错误。
第 2 项可能与第 1 项相关。某些 Bean 未正确代理来处理事务。在我的仅 JUnit 上下文中,我有以下情况:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(public * com.mycompany.package1..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut" />
</aop:config>
我在某些地方收到休眠错误,因为没有事务,而在其他地方,bean 被代理并启动事务。代理和非代理 Bean 都位于 com.mycompany.package1 的子包中。
当然,当我们在 WAS 中运行应用程序时,所有这些都有效。它使用 ContextSingletonBeanFactoryLocator。我也在 JUnit 中尝试过,但似乎没有帮助。
感谢您的任何帮助。
We have an existing Java EE application that leverages Spring and are transitioning from xml configuration to autowiring. We just converted most of our EJBs to Spring beans, but currently still use MDBs and EJB timers.
- WAS 7.0
- Java 6
- Spring 3.0.5
- JUnit 4.8.1
I am also in the process of writing integration tests in JUnit. My integration tests use most of the context configuration files as when running in WAS, but not things that tie into JNDI or use the JTA transaction manager. For those, I have equivalents that setup ActiveMQ queues, a Hibernate transaction manager, etc.
My test looks like this:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/junit-container-context.xml",
"/spring-contexts/service-context.xml",
"/spring-contexts/integration-context.xml",
"/available-tests-context.xml" })
public class TestCase1Runner {
@Autowired
TestCase1 test;
@Autowired
private ApplicationContext applicationContext;
@Before
public void setupErrorHandling() {
// Some setup
}
@Test
@Transactional
public void run() throws Exception {
test.executeTest();
}
}
My tests are having problems for at least a couple of reasons:
- Autowiring skips some beans
- Sometimes beans are not proxied for transactions
Item 1 seems to have something to do with circular references. I made copies of some of the beans that had autowiring problems. I made the copies in the same package. The copy gets wired up, but not the original. I then began to move references in the xml context files from the original to the copy, and at some point, the copy no longer gets wired but the original does. I have the following in one of the context files (with the names changed to protect me :):
<context:component-scan
base-package="com.mycompany.package1,com.mycompany.package2" />
<context:annotation-config />
I think the second entity is redundant, but should be innocuous.
I don't see any errors in the logs. I turned logging to debug and see most of the beans being autowired, but no errors on those Spring seems to skip.
Item 2 might be related to Item 1. Some beans are not properly proxied to handle transactions. In my JUnit-only context, I have the following:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(public * com.mycompany.package1..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut" />
</aop:config>
I am getting hibernate errors in some places because there is no transaction, while in other places, the beans are proxied and transactions are started. Both the proxied and non-proxied beans are in subpackages of com.mycompany.package1
.
Of course, all of this works when we run the application in WAS. It uses a ContextSingletonBeanFactoryLocator. I tried that as well in JUnit, but it has not seemed to help.
Thanks for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您的测试类应该扩展自:
然后您可以使用以下内容配置事务内容:
其中 defaultRollback 定义是否在每次测试后回滚。
I think your test class should extend from:
and then you can configure the transactional stuff with:
where defaultRollback defines whether to rollback after every test.