Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reset my database state after each unit test without making the whole test a transaction?

I'm using Spring 3.1.1.RELEASE, Hibernate 4.1.0.Final, JPA 2, JUnit 4.8.1, and HSQL 2.2.7. I want to run some JUnit tests on my service methods, and after each test, I would like any data written to the in-memory database to be rolled back. However, I do NOT want the entire test to be treated as a transaction. For example in this test

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:test-context.xml" }) public class ContractServiceTest  {     …      @Autowired     private ContractService m_contractService;      @Test     public void testUpdateContract()     {         // Add the contract         m_contractService.save(m_contract);         Assert.assertNotNull(m_contract.getId());         // Update the activation date by 6 months.         final Calendar activationDate = Calendar.getInstance();         activationDate.setTime(activationDate.getTime());         activationDate.add(Calendar.MONTH, 6);         m_contract.setActivationDate(activationDate.getTime());         m_contractService.save(m_contract);         final List<Contract> foundContracts = m_contractService.findContractByOppId(m_contract.getOpportunityId());         Assert.assertEquals(foundContracts.get(0), m_contract);     }   // testUpdateContract 

there are three calls to the service, ("m_contractService.save", "m_contractService.save", and "m_contractService.findContractByOppId") and each is treated as a transaction, which I want. But I don't know how to reset my in-memory database to its original state after each unit test.

Let me know if I need to provide additional information.

like image 862
Dave Avatar asked Jan 15 '13 18:01

Dave


People also ask

Should unit tests touch the database?

It is meant to make sure that definable modules of code work as expected. To test an application it is not enough to use unit tests. You must also perform functional testing and regression testing. Database access falls outside the scope of unit testing, so you would not write unit tests that include database access.

What runs after every test method?

Fixture includes setUp() method which runs before every test invocation and tearDown() method which runs after every test method.

Should unit tests depend on database?

There's no way to test this function without having a database connection available at the time of testing. If a new developer clones the project they will need to set up a database or else tests will fail.


1 Answers

Since you are using Hibernate, you could use the property hibernate.hbm2ddl.auto to create the database on startup every time. You would also need to force the spring context to be reloaded after each test. You can do this with the @DirtiesContext annotation.

This might add a bit extra overhead to your tests, so the other solution is to just manually delete the data from each table.

like image 87
Solubris Avatar answered Sep 19 '22 14:09

Solubris