TransactionalTestExecutionListener使用报异常

使用spring自带框架测试,代码如下:

package TestContext;

import java.util.List;

import javax.annotation.Resource;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

import entity.User;
import service.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:beans.xml")
@TestExecutionListeners(TransactionalTestExecutionListener.class)
@Transactional
public class ListActionTest extends AbstractTransactionalJUnit4SpringContextTests{
	
	
	private UserService userService;
	

	public UserService getUserService() {
		return userService;
	}

	@Resource
	public void setUserService(UserService userService) {
		this.userService = userService;
	}


	//	@Rollback(false)默认true 
	@Test
	public void test(){
		/*User user = userService.getUser(50);
		System.out.println(user.getUname());
		
		List<User> users = userService.getUsers();
		System.out.println(users.size());*/
		
		User user2 = new User();
		user2.setUname("b");
		user2.setPwd("b");
		userService.add(user2);
		
	}
	
}

运行时报错:

警告: Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@15975490] to process 'before' execution of test method [public void TestContext.ListActionTest.test()] for test instance [TestContext.ListActionTest@40dd3977]
java.lang.IllegalStateException: Cannot start a new transaction without ending the existing transaction.
	at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:169)
	at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:265)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

注释掉下面一行注解

//@TestExecutionListeners(TransactionalTestExecutionListener.class)

运行成功。

ListActionTest的父类AbstractTransactionalJUnit4SpringContextTests已经使用的注解

@TestExecutionListeners({TransactionalTestExecutionListener.class, SqlScriptsTestExecutionListener.class})

AbstractTransactionalJUnit4SpringContextTests的父类AbstractJUnit4SpringContextTests又使用了注解

@TestExecutionListeners({ ServletTestExecutionListener.class, DirtiesContextBeforeModesTestExecutionListener.class,
	DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })

所以这6个注解都会自动继承,不需要添加。

而至于为什么一添加

TransactionalTestExecutionListener.class

就报异常,我查了下:

http://stackoverflow.com/questions/19537775/transaction-with-transactional-and-transactionaltestexecutionlistener-what-is-th

一人回答的是:

TransactionalTestExecutionListener is the only guy who creates transactions. It checks @Transactional annotation presence and then opens transaction. In case on test execution listeners are specified spring uses some default test execution listeners one of which is TransactionalTestExecutionListener, that is why it seems that listener and annotation works separately.

他提到TransactionalTestExecutionListener 检测到@Transactional会开启一个transaction。后半段我根据自己理解断了下句如下:

 In case of test execution,  listeners are specified spring, uses some default test execution listeners, one of which is TransactionalTestExecutionListener, that is why it seems that listener and annotation works separately.

简单翻译下就是:当你执行测试时,如果指定了使用spring的监听器,那么会使用一些默认的监听器,而这些默认监听器中的其中一个便是TransactionalTestExecutionListener,这也就是为什么监听器和注解会分开使用的原因。


但是以上解释还是听得云里雾里的,所以我自己总结如下:

加上TransactionalTestExecutionListener 时就报异常java.lang.IllegalStateException: Cannot start a new transaction without ending the existing transaction.。原因是:

我们继承AbstractTransactionalJUnit4SpringContextTests时,已经继承了注解TransactionalTestExecutionListener ,这时再重复使用此注解,即是在原来已经开了一个transaction的基础上又重复开了个transaction.所以会报这个异常。

这一原因只是我个人的猜想,有看到此博客的兄弟,如有更好的解释和evidence,还望不吝赐教。多谢!

转载于:https://my.oschina.net/u/2430057/blog/541418

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值