简体   繁体   中英

Integration testing - Hibernate & DbUnit

I'm writing some integrations tests in JUnit. What happens here is that when i run all the tests together in a row (and not separately), the data persisted in the database always changes and the tests find unexpected data (inserted by the previous test) during their execution.

I was thinking to use DbUnit, but i wonder if it resets the auto-increment index between each execution or not (because the tests also check the IDs of the persisted entities).

Thanks

M.

It's a best practice to put your database in a known state before a test execution and DBUnit provides everything required for that. But don't rely on auto incremented columns, put them also in your DBUnit dataset. Pros: you can manually verify the database state after executing a test that fails. Cons: you need to setup and to maintain datasets.

The other approach is to run each test method inside a transaction (and to rollback the transaction at the end of the execution). Pros: data are easier to setup and maintain (in the databse). Cons: Fixing a failed test is less convenient.

You can either run single tests or if applicable groups of tests as a single transaction, and then roll back at the end. (This might be difficult if the tests themselves comprise multiple transactions and your db doens't support nested transactions or savepoints.)

Alternatively, have your test database created by scripts. DbUnit can help here, as can other database generators, such as LiquiBase , dbmaintain , dbmigrate You can then drop the entire database and recreate for each test or test group. The usefulness of this approach diminishes as the test dataset becomes large and overhead increases.

A final option is to not have your tests depend upon the generated id, since depending upon the generated value will create brittle tests. It's useful to test the generated id, so test these values for some tests, but I'm not sure there is value in testing the Ids for all tests.

EDIT: The OP asked about using hibernate to recreate the schema. This can be arranged by creating a new SessionFactory for each test and setting the "hibernate.hbm2ddl.auto" to "true" when building the SessionFactory. I mention the diminishing effectiveness of drop-create - it appies to this case too.

It is bad to rely on id values in a test, cause auto-increment are database specific only. So i would never check the id's, cause if you do so your test depends that the entities are filled with particular id values which is not a real life example. A test should be independent of auto-increment id's.

Essentially tis issue can be resolved in two ways.

  1. Wrap your DB related tests within a transaction. Before the test begin the transaction. After the test run is over, abort the transaction always abort the transaction. This way no changes made in the test would be retained.

  2. Use something like DBUnit etc. to mock DB operations related classes so that no data ever goes to DB and your classes return results as though DB operation has been done.

If you access to DB when running your tests I prefer approach 1.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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