春季交易管理测试

时间:2009-06-09 17:40:15

标签: java unit-testing spring testing

我想使用SpringContextTests测试我的Dao类 在我的方法类中,我扩展了AbstractTransactionalJUnit4SpringContextTests,以便我的测试类与JUnit4集成。我还设置了配置,并在@Before中的@After和tearDown中清理初始化和数据库。我的测试类很完美。

我的问题是,当我运行我的测试类并且数据库充满了数据时,原始数据没有回滚,我的数据库被清除。在@Before方法中,我清除数据库并填充数据,认为我将能够回滚它,但事实并非如此。

任何人都可以找到一个可以在数据库中工作和回滚信息的示例。

ADDONS:
我的测试方法中的每个数据库操作都会被回滚。但是super.deleteFromTables("person")方法中@Before的执行没有从数据库中回滚所有以前的数据。

Spring回滚所有CRUD操作,但在事务不回滚之前清理数据库。

8 个答案:

答案 0 :(得分:2)

感谢所有回答我问题的人。我从那些答案中学到了很多东西,但它并没有解决我的问题 我知道我的测试数据可以进行事务管理,并且可以正常工作 这个错误就在我身上
我忘记了有关数据库命令的教训,当您在DML语句之后执行DDL语句时,它将自动提交事务。我在DML之后执行了一个DDL,删除了所有记录,然后ALTER表的AUTO_INCREMENT,其中的{{1}}将导致自动提交并永久删除表的所有记录。

固定情景解决了我的问题。

答案 1 :(得分:1)

可能的原因:

  • 您正在使用没有正确交易的数据库/数据库引擎;
  • 您正在使用多个事务管理器和/或数据源,并且未选择正确的事务管理器和/或数据源;
  • 你在测试课中做自己独立的交易

至于一个例子,这是一个(我的头脑,未编译)

public class DBTest extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private SomeDAO _aBeanDefinedInMyContextFile;

    @Test
    public void insert_works() {
        assert _aBeanDefinedInMyContextFile.findAll() == 0;
        _aBeanDefinedInMyContextFile.save(new Bean());
        assert _aBeanDefinedInMyContextFile.findAll() == 1;
    }


}

关键点:

  • SomeDAO是一个接口,对应于在我的上下文中声明的bean;
  • bean没有任何事务设置(通知/程序),它依赖于调用者是事务性的 - 生产中的服务,或者我们情况下的测试;
  • 测试不包含任何事务管理代码,因为它都是在框架中完成的。

答案 2 :(得分:1)

我不确定你班上有什么问题。以下是使用dbunit和spring 2.5执行所需操作的类的摘录:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
  "testContext.xml"})
@TransactionConfiguration
@Transactional
public class SampleDAOTest {

    @Autowired
    private DataSource dataSource;
    @Autowired
    private SampleDAO sampleDAO;

    @Before 
    public void onSetUpInTransaction() throws Exception {
        //Populate Test data
        IDatabaseConnection dbUnitCon = new DatabaseConnection(DataSourceUtils.getConnection(dataSource), "DATASOURCE");
            //read in from a dbunit excel file of test data
        IDataSet dataSet = new XlsDataSet(new File("src/test/resources/TestData.xls"));
        DatabaseOperation.INSERT.execute(dbUnitCon, dataSet);
    }


    @Test
    public void testGetIntermediaryOrganisation() {

        // Test getting a user
        User object = sampleDAO.getUser(99L);
        assertTrue(object.getValue);


    }
}

此方法的一个优点是您不需要扩展任何类。因此,您仍然可以拥有自己的测试层次结构。

如果你真的想坚持使用当前的方法,而不是使用@before注释我瘦,你需要覆盖下面的方法并将你的设置代码放在那里。

@Override
public void onSetUpInTransaction() throws Exception {...}

希望这有帮助

答案 3 :(得分:0)

对于您的问题,我建议您使用单独的数据库实例来运行您的测试。这样,您可以安全地擦除它并让测试根据需要进行初始化。

据我所知,数据库测试的Spring支持类只回滚测试中发生的事情,而不是在测试的设置和拆卸中发生的事情。

答案 4 :(得分:0)

同意Confusion--您应该针对自己的数据库架构运行测试。

有了这个,你可以将你的休眠属性设置为'create-drop':

  

使用create-drop,数据库架构   将被删除时   SessionFactory显式关闭。

请参阅:Optional Hibernate Config properites

示例摘录:

<bean id="sessionBean" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
         ...etc

答案 5 :(得分:0)

虽然我同意这个人建议使用decored db进行测试,但没有任何理由说使用填充的db不起作用,@ Before和@After方法都在事务上下文中执行,因此应该回滚更改。

候选条件:

  • 数据设置正在执行非事务性的操作(即DDL语句)
  • 测试中的某些内容实际上是在提交事务

你可以发布@Before方法,我只是想知道你是在清理表还是实际丢弃并重新创建它们?

答案 6 :(得分:0)

据我所知,通过查看AbstractJUnit4SpringContextTests和TransactionalTestExecutionListener的Javadocs和源代码,您需要注释要使用@Transactional进行事务处理的测试方法。

还有@BeforeTransaction和@AfterTransaction注释,您可以更好地控制事务中的运行。

我建议您创建使用所有这些注释注释的方法,包括@Before,然后在这些方法中使用断点运行测试。通过这种方式,您可以查看堆栈并确定spring是否已为您启动了事务。如果您在堆栈中看到类似“TransactionInterceptor”的内容,或者名称中包含“Transaction”的任何内容,那么您很可能正在进行交易。

答案 7 :(得分:0)

您在@Before方法中执行super.deleteFromTables,该方法位于tx内。那么如果tx被回滚,那么删除也不会被回滚吗?

相关问题