Does spring junit rollback by default? - java

I'm testing my DAO layer using Spring and Junit. This is my test:
#ContextConfiguration(locations = "classpath:application-context-test.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class TestEmployeeDAO {
#Autowired
private EmployeeDAO employeeDAO;
#Test
#Transactional
public void testInsertEmployee(){
Employee employee = new Employee("Abdel Karim");
employeeDAO.insert(employee);
.
.
.
}
}
}
But when i execute the test and i check my database i find that no row is inserted, and no exception is thrown. I don't understand why, does the default behaviour of Spring (SpringJUnit4ClassRunner) is to rollback the transaction?
Thanks in advance.

Yes, by default rollback is true. To switch it off use:
#Test
#Transactional
#Rollback(false)
public void testInsertEmployee(){
Employee employee = new Employee("Abdel Karim");
employeeDAO.insert(employee);
}

Related

Spring Boot tests. Initilize database programatically

I develope a WebApp using Spring Boot. I need to make integration tests with database. I have a problem in database initilization. I know it is possible to prepare database with initilazion scripts. And I do it partially. But some records have type of BLOB and it is annoying to initilize it by the script. So I'm trying to init this records programatically from #Test method using CrudRepository implementations from ApplicationContext (that are encapsulated in PersistenceService).
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class, DbUnitTestExecutionListener.class})
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#DatabaseSetup(MyTest.DATASET)
#DatabaseTearDown(type = DatabaseOperation.DELETE_ALL, value = { MyTest.DATASET })
#DirtiesContext
public class MyTest {
protected static final String DATASET = "classpath:dbunit/customer.xml";
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private PersistenceService persistenceService;
#Test
#Transactional
#Rollback(false)
public void afterGroupDeleteCrlShouldContainsAllCertificates() throws Exception {
prepareDatabase(persistenceService);
restTemplate.delete("/customer/");
}
But marking of #Test method by #Transactional is the reason of deadlock when I'm calling restTemplate.delete() because there is uncommited transaction.
So I'm trying to commit transaction manually adding after calling of prepareDatabase(persistenceService) this snippet:
if (TestTransaction.isActive()) {
TestTransaction.flagForCommit();
TestTransaction.end();
}
This snippet fixes deadlock but generate SQLException after test execution
java.sql.SQLException: PooledConnection has already been closed.
I'm sure it is common task. But I don't know how to resolve it gracefully.
I think I'm missing some parts, but how about putting the prepareDatabase into a #Before method in your test.
#Before
public void setupDatabaseForEachTest(){
prepareDatabase(persistenceService);
}
I think that will allow your #Test to be #Transactional and give you the desired results.

Transaction roll back is not working in test case in #Nested class of JUnit5

I use spring-boot, JUnit5, Mybatis.
#SpringJUnitJupiterConfig(classes = {RepositoryTestConfig.class})
#MapperScan
#Rollback
#Transactional
public class TestClass {
#Autowired
private TestMapper testMapper;
#BeforeEach
void init() {
User user = new User();
testMapper.insert(user);
}
#Test
public void test1() {
// (1) success rollback
}
#Nested
class WhenExistData {
#Test
public void test2() {
// (2) rollback not working
}
}
}
(1) is working rollback. And the following log is output.
2017-05-26 22:21:29 [INFO ](TransactionContext.java:136) Rolled back transaction for test context ...
But, (2) is not working. I want to be able to roll back into #Nested.
This is to be expected: the Spring TestContext Framework has never supported "inheritance" for nested test classes.
Thus your "work around" is actually the correct way to achieve your goal at this point in time.
Note, however, that I may add support for "pseudo-inheritance" for nested test classes in conjunction with SPR-15366.
Regards,
Sam (author of the Spring TestContext Framework)
I solved it in the following way..
#SpringJUnitJupiterConfig(classes = {RepositoryTestConfig.class})
#MapperScan
#Rollback
#Transactional
public class TestClass {
#Autowired
private TestMapper testMapper;
#BeforeEach
void init() {
User user = new User();
testMapper.insert(user);
}
#Nested
#SpringJUnitJupiterConfig(classes = {RepositoryTestConfig.class})
#MapperScan
#Rollback
#Transactional
class WhenExistData {
#Test
public void test2() {
}
}
}
I solved it in the following way
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
// JUnit5
#SpringBootTest
public class TestClass {
#Resource
private TestMapper testMapper;
#Test
#Rollback
#Transactional
public void createByTimerId() {
Assertions.assertEquals(1, testMapper.insert());
}
}
Using the annotation NestedTestConfiguration from Spring on the enclosing class did the trick for me. It seems that without it, the nested class won't inherit the config.
#NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.INHERIT)
So maybe on your TestClass you would have your current annotations and then:
#NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.INHERIT)
public class TestClass {
...

#Transactional does not rollback in JUnit test

I have 2 JUnit tests in the same test class each one marked as #Transactional, the first one create users and the second one create users and check that we can get these users.
The problem is that when the second test runs, users created by the first test is still in the DB.
#Test
#Transactional
public void testCreateUser() throws Exception
#Test
#Transactional
public void testGetUserById() throws Exception
Do you have any idea why #Transactional is not working well in the same test class? Furthermore data is rolled back at the end of the test class.
I'm using Spring boot + Mysql + Hibernate.
Thank you for your time.
Try something like this and take care about classpath of your ...context.xml.
You can also move #Transactional above class if you want every method to be transactional or above each method you want.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:/config/your-context.xml","classpath:/config/ehcache.xml"})
#Transactional
#WebAppConfiguration
public class IntegrationTests {
#Autowired
private ApplicationContext appContext;
#Autowired
public FileDao fileDao;
#Autowired
public SessionFactory sessionFactory;
#Test
public void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException{
....
....
....
}
}
Add to configuration class #EnableTransactionManagement

How to rollback transaction after class (using TestNg and Spring)?

Let's say we have the next test:
#ContextConfiguration(classes = {MyDaoContext.class})
public class MyDaoTest extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private MyDao dao;
#Test
public void insertDataTest() {
// insert data here and test something
}
#Test(dependsOnMethods = "insertDataTest")
public void modifyPreviouslyInsertedDataTest() {
// get previously inserted data and test something
}
}
Second test will fall because when we have finished first test the inserted data are gone.
Is there a way to rollback a transaction after all tests have finished their work?
Each test runs in its own transaction and rollbacks at the end. You can tune that by adding #Rollback(false) to your first test.
The problem now is that the transaction of insertDataTest has completed so you should remove what it has created manually. To do that, the class you extends from has several utility methods such as deleteFromTables or deleteFromTableWhere.
This should go ideally in an #AfterClass or something.
But that's not what I would do. I would factor out the data that are inserted by insertDataTest in a shared utility. That way, you could call it again in your second test and remove the dependsOnMethods. Having such dependency is not recommended as you can't run that test in isolation.
Try the following (which would work in JUnit, I'm not sure about TestBG)
#ContextConfiguration(classes = {MyDaoContext.class})
public class MyDaoTest extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private MyDao dao;
#Test
#Rollback(false)
public void insertDataTest() {
// insert data here and test something
}
#Test(dependsOnMethods = "insertDataTest")
public void modifyPreviouslyInsertedDataTest() {
// get previously inserted data and test something
}
}
In that case of course you would have to delete the data from the first method manually

JUnit: Setting Transaction boundry for Test Class

I want to start the database transactions before start of any test method and rollback all transactions at the end of running all tests.
How to do thing?What annotations should I use ?
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/testApplicationContext.xml"})
public class MyTests{
public void setUp(){
//Insert temporary data to Database
}
#Test
public void testOne(){
//Do some DB transactions
}
#Test void testTwo(){
//Do some more DB transactions
}
public void tearDown(){
//Need to rollback all transactions
}
}
In Spring just add #Transactional annotation over your test case class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/testApplicationContext.xml"})
#Transactional //CRUCIAL!
public class MyTests{
Check out official documentation for very in-depth details, including #TransactionConfiguration, #BeforeTransaction, #AfterTransaction and other features.
Use #Before to launch method before any test and #After to launch method after every test. Use #Transactional spring's annotation over a method or over a class to start transaction and #Rollback to rollback everything done in transaction.
#Before
public void setUp(){
//set up, before every test method
}
#Transactional
#Test
public void test(){
}
#Rollback
#After
public void tearDown(){
//tear down after every test method
}
Also there is same issue solved in another way.
Use the annotation #Before for methods that have to run before every testmethod and #After to run after every testmethod.
You can take this article as a reference.

Categories