文档章节

TransactionalTestExecutionListener使用报异常

liuhuics10
 liuhuics10
发布于 2015/12/09 13:40
字数 680
阅读 228
收藏 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
Hibernate中get和load的区别

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

1314Stone
2017/11/24
0
0
Iterator/foreach遍历list时,删除元素的报错问题

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

KingJack灬
2017/12/07
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

没有更多内容

加载失败,请刷新页面

加载更多

自己手写一个 SpringMVC 框架

前端框架很多,但没有一个框架称霸,后端框架现在Spring已经完成大一统.所以学习Spring是Java程序员的必修课. Spring 框架对于 Java 后端程序员来说再熟悉不过了,以前只知道它用的反射实现的,...

别打我会飞
8分钟前
0
0
01-《Apache Tomcat 9》之文件索引

《Apache Tomcat 9》是《看Apache官方文档学英语》的第一个专栏!让我们一起在看文档的过程中学英语,在学英语的过程中夯实技术! Documentation Index - 文件索引 Introduction - 介绍 This...

飞鱼说编程
10分钟前
0
0
最近

20181016最近在熟悉业务 关于money的 要涉及到流程中转同步 这个点感觉 业务大于技术 关于业务性的内容 还是要把自己及时清零的好 我们需要好好的梳理下业务内容 业务作为导向 技术提供解决方...

JAVA码猿
19分钟前
0
0
JDK1.8HashMap源码分析

HashMap和Hashtable的主要区别是: 1. Hashtable是线程安全,而HashMap则非线程安全,Hashtable的实现方法里面大部分都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高...

小小明童鞋
29分钟前
14
0
以Redis为例,详谈分布式系统缓存的细枝末节

前言: 在分布式Web程序设计中,解决高并发以及内部解耦的关键技术离不开缓存和队列,而缓存角色类似计算机硬件中CPU的各级缓存。如今的业务规模稍大的互联网项目,即使在最初beta版的开发上...

Java干货分享
32分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部