使用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
一人回答的是:
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,還望不吝賜教。多謝!