文档章节

TransactionalTestExecutionListener使用报异常

liuhuics10
 liuhuics10
发布于 2015/12/09 13:40
字数 680
阅读 211
收藏 0

使用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,还望不吝赐教。多谢!

© 著作权归作者所有

共有 人打赏支持
liuhuics10
粉丝 4
博文 97
码字总数 39010
作品 0
烟台
Linux inode满导致创建文件报磁盘空间不足

客户报不能挂载存储,系统异常。登陆系统,尝试手动mount分区,报失败。进入挂载点,尝试写入一个文件,报磁盘空间不足,首先怀疑是系统磁盘空间满: $ df Filesystem 1K-blocks Used Avail...

月中井
2014/05/19
0
0
Iterator/foreach遍历list时,删除元素的报错问题

今天遇到一个问题,代码如下: 创建了一个,然后给他了4个元素,将转为然后进行遍历,在遍历过程中对list进行,在测试的过程中,发现居然会出现报错现象,一直想不明白,后来根据报错信息去查...

KingJack灬
2017/12/07
0
0
Hibernate中get和load的区别

作者博客@Stone原地址 在Hibernate中如果要从数据库中得到一个对象 两种方法 通过session.get()方法 通过session.load()方法 区别 load加载方式 当使用load方法来得到一个对象时,此时hiber...

1314Stone
2017/11/24
0
0
MyBatis3传递空值参数报异常的解决

MyBatis3传递空值参数报异常的解决 在使用Mybatis 3时,发现了这个问题,当插入数据时,如果有一个字段为空值时,系统会报异常,导致插入数据失败。异常信息类似:org.springframework.jdbc....

五大三粗
2015/09/23
224
0
CopyOnWriteArrayList的排序方法

在多线程中,使用ArrayList 进行remove操作时,会报异常。改用CopyOnWriteArrayList,若再进Collections.sort(copyOnWriteArrayList, myComparator)时,会报异常: java.lang.UnsupportedOpe...

liuhuics10
2016/03/25
103
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

es6

在实际开发中,我们有时需要知道对象的所有属性,原生js给我们提供了一个很好的方法:Object.keys(),该方法返回一个数组 传入对象,返回属性名 var obj = {'a':'123','b':'345'};console.l...

不负好时光
13分钟前
0
0
叮!您收到一份超值Java基础入门资料!

摘要:Java语言有什么特点?如何最大效率的学习?深浅拷贝到底有何区别?阿里巴巴高级开发工程师为大家带来Java系统解读,带你掌握Java技术要领,突破重点难点,入门面向对象编程,以详细示例...

全部原谅
15分钟前
0
0
web.xml容器加载顺序

容器对于web.xml的加载过程是context-param >> listener >> fileter >> servlet

Aeroever
17分钟前
1
0
Docker容器日志查看与清理

1. 问题 docker容器日志导致主机磁盘空间满了。docker logs -f container_name噼里啪啦一大堆,很占用空间,不用的日志可以清理掉了。 2. 解决方法 2.1 找出Docker容器日志 在linux上,容器日...

muzi1994
18分钟前
0
0
J2Cache 和普通缓存框架有何不同,它解决了什么问题?

不少人看到 J2Cache 第一眼时,会认为这就是一个普普通通的缓存框架,和例如 Ehcache、Caffeine 、Spring Cache 之类的项目没什么区别,无非是造了一个新的轮子而已。事实上完全不是一回事!...

红薯
21分钟前
414
14

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部