简体   繁体   English

春季交易管理测试

[英]Spring Transaction Management Test

I want to test my Dao Class using the SpringContextTests. 我想使用SpringContextTests测试我的Dao类。
In my method class I extended the AbstractTransactionalJUnit4SpringContextTests in order for my test class to integrate with JUnit4. 在我的方法类中,我扩展了AbstractTransactionalJUnit4SpringContextTests ,以使我的测试类与JUnit4集成。 I have also set up the configurations and made the initialization and database clean up in the @Before and tearDown in the @After . 我还设置了配置,并在@Before初始化和数据库清理,在@After清除了@Before My test class works perfectly. 我的测试课效果很好。

My problem was, when I run my test class and the database is filled with data, the original data was not rolled back and my database is cleared. 我的问题是,当我运行测试类并在数据库中填充了数据时,原始数据没有回滚并且数据库被清除了。 In the @Before method, I clear the database and populate data, thinking that I will be able to rollback it but its not. @Before方法中,我清除数据库并填充数据,以为我可以回滚数据库,但不能回滚。

Can anyone site an example that works and rollbacks information in the database. 任何人都可以找到可以正常工作的示例并回滚数据库中的信息。

ADDONS: ADDONS:
Every database manipulation in my test methods are rolled back. 我的测试方法中的每个数据库操作都会回滚。 But the execution of super.deleteFromTables("person") in the @Before method did not rollback all the previous data from the database. 但是在@Before方法中执行super.deleteFromTables("person")并不会回滚数据库中所有以前的数据。

Spring rollbacks all the CRUD operations but the database clean up before the transaction do not rollback. Spring回滚所有CRUD操作,但在不回滚事务之前清理数据库。

Thank you to all those who answered my question. 谢谢所有回答我问题的人。 I learned a lot from those answers but it didn't solve my problem. 我从这些答案中学到了很多东西,但是并不能解决我的问题。
I knew my test data does a transaction management and it does its job properly. 我知道我的测试数据可以进行事务管理,并且可以正常工作。
The mistake is on my part. 这是我的错。

I forgot the lesson about database commands that when you execute a DDL statement after a DML statement, it will automatically commit the transaction. 我忘记了有关数据库命令的课程,当您在DML语句之后执行DDL语句时,它将自动提交事务。 I executed a DDL after a DML by deleting all record and then ALTER the AUTO_INCREMENT of the table where in it will cause an auto-commit and delete all records of the table permanently. 我在DML之后执行DDL,方法是删除所有记录,然后ALTER表的AUTO_INCREMENT ,这将导致自动提交并永久删除表的所有记录。

FIXING THAT SCENARIO SOLVED MY PROBLEM. 解决该场景解决了我的问题。

Possible causes: 可能的原因:

  • you're using a database/database engine which does not have proper transactions; 您使用的数据库/数据库引擎没有适当的交易;
  • you're using multiple transaction managers and/or data sources and the proper one is not picked up; 您正在使用多个事务管理器和/或数据源,但未选择正确的一个;
  • you're doing your own, separate, transactions in the test class 您在测试课程中进行自己的独立交易

As for an example, here's one ( top of my head, not compiled ) 例如,这是一个(我的头顶,未编译)

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


}

Key points: 关键点:

  • the SomeDAO is an interface which corresponds to a bean declared in my context; SomeDAO是一个接口,它对应于在我的上下文中声明的Bean;
  • the bean does not have any transactional settings ( advice/programmatic), it relies on the caller being transactional - either the service in production, or the test in our situation; Bean没有任何事务性设置(建议/编程),它依赖于调用者是事务性的-生产中的服务或我们情况下的测试;
  • the test does not include any transactional management code, as it's all done in the framework. 该测试不包含任何事务管理代码,因为它们都是在框架中完成的。

I'm not sure what is wrong with your class. 我不确定您的课有什么问题。 Here is an extract of a class that does what you want with dbunit and spring 2.5: 这是一个类的摘录,该类使用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);


    }
}

One of the benfits of this method is that you don't need to extend any classes. 此方法的优点之一是您不需要扩展任何类。 So you can still have your own hierarchy for tests. 因此,您仍然可以拥有自己的测试层次结构。

If you really want to stick to your current method instead of using the @before annotation I thinnk you need to overide the below method and put your setup code in there. 如果您真的想坚持使用当前方法而不是使用@before注释(我稀疏),则需要覆盖以下方法,并将您的安装代码放入其中。

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

Hope this helps 希望这可以帮助

You're doing super.deleteFromTables in your @Before method which is within the tx. 您正在tx中的@Before方法中执行super.deleteFromTables。 So if the tx is rolled back doesn't the deletions get rolled back also? 因此,如果tx被回滚,删除的内容也不会回滚吗?

Sidestepping your question, I suggest that you use a seperate database instance to run your tests against. 避开您的问题,我建议您使用单独的数据库实例来运行测试。 That way, you can safely wipe it clean and have your tests initialize it as required. 这样,您可以安全地将其擦拭干净,并使测试根据需要对其进行初始化。

As far as I know the Spring support classes for database testing only rollback what happens in the tests, not what happens in setup and teardown of tests. 据我所知,用于数据库测试的Spring支持类仅回滚测试中发生的事情,而不回退测试的设置和拆卸中发生的事情。

Agree with Confusion-- you should be running your tests against their own database schema. 同意混淆-您应该针对自己的数据库架构运行测试。

With this, you can set your hibernate properties to 'create-drop': 这样,您可以将休眠属性设置为“ create-drop”:

With create-drop, the database schema will be dropped when the SessionFactory is closed explicitly. 使用create-drop时,显式关闭SessionFactory时将删除数据库架构。

See: Optional Hibernate Config properites 请参阅: 可选的Hibernate Config属性

Example snippet: 示例片段:

<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

While I'd agree with the guy's suggesting a deciated db for testing, there isn't any reason why using a populated db shouldn't work, both @Before and @After methods are executed within the transactional context, therefore there changes should be rolledback. 虽然我同意那个家伙建议使用经过测试的db进行测试的观点,但没有任何理由不能使用填充的db,因为@Before和@After方法都在事务上下文中执行,因此应该进行更改回滚。

Possibles: 候选条件:

  • The data setup is doing something that isn't transactional (ie DDL statements) 数据设置正在执行非事务性的操作(即DDL语句)
  • Something in your test is actually committing the transaction 测试中的某些内容实际上是在提交事务

Can you post the @Before method, I'm just wondering if you are just clearing the tables or actually dropping and recreating them? 您可以发布@Before方法吗,我想知道您是要清除表还是实际删除并重新创建它们?

As far as I can tell, by looking at the Javadocs and source code for AbstractJUnit4SpringContextTests and TransactionalTestExecutionListener you need to annotate your test methods you want transactionalised with @Transactional. 据我所知,通过查看AbstractJUnit4SpringContextTests和TransactionalTestExecutionListener的Javadocs和源代码,您需要注释要使用@Transactional进行事务化的测试方法。

There are also @BeforeTransaction and @AfterTransaction annotations where you can better control what runs in a transaction. 还有@BeforeTransaction和@AfterTransaction批注,您可以在其中更好地控制事务中运行的内容。

I suggest you create methods annotated with all these annotations, including @Before and then run the test with breakpoints at these methods. 我建议您创建使用所有这些注释(包括@Before)注释的方法,然后使用这些方法的断点运行测试。 That way you can look at the stack and work out whether spring has started a transaction for you or not. 这样,您可以查看堆栈并确定spring是否为您启动了事务。 If you see something like "TransactionInterceptor" in the stack then, or anything else with "Transaction" in the name, then chances are you're in a transaction. 如果您在堆栈中看到诸如“ TransactionInterceptor”之类的东西,或者名称中带有“ Transaction”之类的其他东西,则可能是您正在进行事务处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM