在非调试模式下,Spring @transaction在junit中没有像预期的那样工作

所有MyService方法都是事务性的。 在下面的junit测试中,获取物品数量,保存一个新物品,并获得物品数量以确保物品数量增加1。

public class MyTest extends ServiceTest{

    1. int countBefore = myService.getCount();    //return n
    2. myService.add(item);                       //item is really added to DB
    3. int countAfter  = myService.getCount();    //return n (sometimes n+1)
}

@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED)
getCount(){…}

@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.SERIALIZABLE)
add(){…}

@Ignore
@ContextConfiguration(locations = { "file:src/main/resources/xxx-context.xml", 
                                    "file:src/main/resources/xxx-data.xml", 
                                    "file:src/main/resources/xxx-services.xml"  })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)
@TestExecutionListeners( {  DependencyInjectionTestExecutionListener.class,
                            DirtiesContextTestExecutionListener.class,
                            TransactionalTestExecutionListener.class,
                            TestListener.class})

public class ServiceTest extends AbstractUT{

@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners( {TestListener.class})
public class AbstractUT{

当调试(3.)返回n + 1这是我想要的。 但是,在没有调试的情况下运行测试时,我得到n

即使有时在运行测试时,我也会得到n + 1,并且下次我得到n,并且在比较两次执行之间的std输出时,它看起来完全一样。 我已启用log4j.logger.org.springframework.transaction = TRACE,我可以看到:

Initializing transaction synchronization
Getting transaction for MyService.getCount
...
Completing transaction for MyService.getCount
Clearing transaction synchronization

...

Initializing transaction synchronization
Getting transaction for MyService.add
...
Completing transaction for MyService.add
Clearing transaction synchronization

...

Initializing transaction synchronization
Getting transaction for MyService.getCount
...
Completing transaction for MyService.getCount
Clearing transaction synchronization

因此,交易正在一个接一个地执行,但怎么可能(3.)没有看到保存的项目?

交易管理是按照我的测试课程设置的:https://stackoverflow.com/a/28657650/353985

我怎样才能找到问题所在? 谢谢!


有类似的问题,但在我的情况下,它并没有回滚。 似乎你忘了添加@Transactional。 从文档(链接)

交易管理

在TestContext框架中,事务由默认配置的TransactionalTestExecutionListener管理,即使您未在测试类中显式声明@TestExecutionListener。 但是,要启用对事务的支持,您必须在通过@ContextConfiguration语义加载的ApplicationContext中配置一个PlatformTransactionManager bean(更多详细信息在下面提供)。 另外,您必须在类或方法级别为测试声明Spring的@Transactional注释。

以上是链接的示例。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
public class FictitiousTransactionalTest {

@BeforeTransaction
public void verifyInitialDatabaseState() {
    // logic to verify the initial state before a transaction is started
}

@Before
public void setUpTestDataWithinTransaction() {
    // set up test data within the transaction
}

@Test
// overrides the class-level defaultRollback setting
@Rollback(true)
public void modifyDatabaseWithinTransaction() {
    // logic which uses the test data and modifies database state
}

@After
public void tearDownWithinTransaction() {
    // execute "tear down" logic within the transaction
}

@AfterTransaction
public void verifyFinalDatabaseState() {
    // logic to verify the final state after transaction has rolled back
}

}


我发现到目前为止通过测试的解决方案是将断言置于afterTransaction方法中

公共类MyTest扩展ServiceTest {

@Test
public void test(){
    1. int countBefore = myService.getCount();    //return n
    2. myService.add(item);                       //item is really added to DB
}
@AfterTransaction
public void verifyFinalDatabaseState() {
    3. int countAfter  = myService.getCount();    //return n (sometimes n+1) 
                                                  //Now always return n+1
}

我会在评论中提出这个问题,但是由于我的声誉不允许,我只想提供一个答案。

您可能正在使用缓存计数查询结果的ORM。 根据add / getCount方法的实现方式以及ORM和数据源的配置,在第二次调用getCount时,您可能会获得在第一次调用getCount期间获得的缓存值。

然而,这并不能解释为什么在调试模式下你总能得到正确的结果。

链接地址: http://www.djcxy.com/p/24961.html

上一篇: Spring @transaction not working as expected in junit in non debug mode

下一篇: ggplot2: merge legends for geom