TransactionalTestExecutionListener使用報異常

使用spring自帶框架測試,代碼以下:java

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);
		
	}
	
}

運行時報錯:spring

警告: 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)

運行成功。eclipse

ListActionTest的父類AbstractTransactionalJUnit4SpringContextTests已經使用的註解ide

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

AbstractTransactionalJUnit4SpringContextTests的父類AbstractJUnit4SpringContextTests又使用了註解測試

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

因此這6個註解都會自動繼承,不須要添加。this

而至於爲何一添加lua

TransactionalTestExecutionListener.class

就報異常,我查了下:spa

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,還望不吝賜教。多謝!

相關文章
相關標籤/搜索