#Rollback in TestNG Integration Test but entry in DB committed - spring

#ContextConfiguration(classes = { ServiceConfig.class,PersistenceConfiguration.class, MailConfig.class })
#Transactional
public class CreateStatsIT extends AbstractTestNGSpringContextTests {
#Autowired
private UserRepository userRepository;
#Test
#Rollback
#Transactional
public void insertUserIT() {
User u = new User(1L, "Test");
u = userRepository.save(s);
List<User> us = userRepository.findAll();
System.out.println(us.size());
}
}
I would expect that the user would not be present in the database after the completion of the test but it is. The Spring Integration Tests documentation describes that the tests rollback automatically and also that #Rollback does not let the transaction be committed.
What am I doing wrong?

Related

Jpa Auditing test null in getCreatedBy, and getLastModifiedBy

Hi I am trying to write unit test for Auditing
#DataJpaTest
#EnableJpaAuditing
#RunWith(SpringRunner.class)
#AutoConfigureEmbeddedDatabase(type=POSTGRES)
public class MyTestAuditor {
#Autowired
private TestEntityManager entityManager;
#Test
public void auditTest() throws InterruptedException {
final MyEntity testEntity = MyEntity.builder()
....
.build();
SLOEntity entity = entityManager.persistAndFlush(testEntity);
assertNotNull(testEntity.getCreatedOn());
assertNotNull(testEntity.getLastModifiedOn());
assertNotNull(testEntity.getCreatedBy());
assertNotNull(testEntity.getLastModifiedBy());
}
}
I pass first two assertion, the timestamp ones, but fail the username part. Is there anything I am missing here, thanks:)

Testing dao layer with #DataJpaTest

I am writing unit testing using #DataJpaTest. Though it should do automatic rollback after every method, it is not doing that. Can you please help me with this.
This has 2 test cases written, ideally, test2 should return null, but it returns 1.
#RunWith(SpringRunner.class)
#DataJpaTest
public class EmployeeRepositoryTest {
#Autowired TestEntityManager em;
#Autowired EmployeeRepository rep;
// #Autowired EmployeeService service;
//Spring context loaded only once, reused by other methods
#Test
public void test1() {
// System.out.println(service); No such bean found
Employee e= new Employee();
e.setName("Payal");
em.persist(e);
em.flush();
Employee emp=rep.findByName("Payal");
assertNotNull(emp);
assertThat(emp.getId()).isGreaterThan(0);
}
#Test
public void test2() {
Employee emp=rep.findByName("Payal");
assertNull(emp);
}
}
Complete code can be found at:
https://github.com/payalbnsl/SpringUnitTestDemo/tree/master/src/test/java/com/example/demo/dao

Using #SpyBean with #Qualifier Spring Boot Test

I have 2 DataSources in my app.
So, to get the required JdbcTemplate, i use #Qualifier. But, when i do like below, the test runs... but stays waiting indefinitely, if there is any use of JdbcTemplate in the "Method Under Test".
#Service
#Transactional
public class SampleDatabaseService {
#Autowired
#Qualifier("firstDbJdbcTemplate")
private JdbcTemplate firstDbJdbcTemplate;
#Autowired
#Qualifier("secondDbJdbcTemplate")
private JdbcTemplate secondDbJdbcTemplate;
#Cacheable("status")
public Map<String, Device> readAllValidDeviceStatus() {
Map<String, Device> allDeviceStatuses = new HashMap<>();
//Stops at below line indefinitely if "SpyBean" is used
List<StatusDetail> statusDetails = firstDbJdbcTemplate
.query(SqlQueries.READ_DEVICE_STATUS, BeanPropertyRowMapper.newInstance(StatusDetail.class));
statusDetails
.stream()
.filter(deviceStatus -> deviceStatus.getName() != "Some Invalid Name")
.forEach(deviceStatus -> allDeviceStatuses
.put(deviceStatus.getName(), buildDevice(deviceStatus)));
return allDeviceStatuses;
}
/** More Stuff **/
}
and the Test :
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#Transactional
#Rollback
#ActiveProfiles("test")
public class SampleDatabaseServiceTest {
#SpyBean
#Qualifier("firstDbJdbcTemplate")
private JdbcTemplate firstDbJdbcTemplate;
#Autowired
private SampleDatabaseService serviceUnderTest;
#Before
public void populateTables() {
//Insert some Dummy Records in "InMemory HSQL DB" using firstDbJdbcTemplate
}
#Test
public void testReadAllValidDeviceStatus() {
// When
Map<String, Device> allDeviceStatuses = serviceUnderTest.readAllValidDeviceStatus();
// Then
assertThat(allDeviceStatuses).isNotNull().isNotEmpty();
// More checks
}
/* More Tests */
}
But, when i replace the #SpyBean with #Autowired in Test, it works fine.
Why is it so? Any help is greatly appreciated. :)
Use it in below format
#MockBean(name = "firstDbJdbcTemplate")
private JdbcTemplate firstDbJdbcTemplate;

Spring boot and Security Integration test with EntityManager

I want to test my spring application. It requires authentication, so I create an user object and persist it in #Before method. But i can not do authentication because, as i think, init() method is executed in another session.
IntegrationTest class:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
#Transactional
public class IntegrationTest {
#PersistenceContext
private EntityManager entityManager;
#Autowired
private PasswordEncoder passwordEncoder;
#LocalServerPort
int port;
private String URL;
#Before
public void init() {
User user = new User();
user.setUsername("testUser");
user.setPassword(passwordEncoder.encode("test"));
user.setEmail("test#test.com");
user.setEnabled(true);
entityManager.persist(user);
entityManager.flush();
entityManager.clear();
RestAssured.port = port;
URL = "http://localhost:" + String.valueOf(port) + "/users/user";
}
#Test
public void givenNotAuthenticatedUser_whenLoggingIn_thenCorrect() {
final RequestSpecification request = RestAssured.given().auth().basic("testUser", "test");
request.when().get(URL).then().assertThat().statusCode(200);
}
}
But if I use my userRepository and call
userRepository.save(user);
instead of
entityManager.persist(user);
entityManager.flush();
entityManager.clear();
everything works fine. I also have to remove #Transactional annotation.
Firstly I thought it was because, there was no commit - I saw that there is no changes in the user table. How to force EntityManager to commit data?
How to use EntityManager in test? And why UserRepository does work well?
As stated in the documentation:
By default, the framework will create and roll back a transaction for each test.
You can override it using #Commit on your test class and put TestTransaction.end() after entityManager.clear().
Now the test works ok but I still can not understand why and how UserRepository works without commiting the transaction.

Spring Test Transaction Rollback Problem

i have a Problem understanding the #Transactional and #TransactionConfiguration(defaultRollback = true) Annotations.
I have a test Code which inserts a userAccount into the Database, then another account with the same name should be inserted, which should result in a DataIntegrityViolationException because the AccountName is marked as Unique. This works fine if #Transactional and #TransactionConfiguration(defaultRollback = true) is not sepcified at the TestClass level. But if Rollback is enabled i don't get the Exception because even in the same method the Data is not inserted into the databasse. If i set a breakpoint after inserting the first Account, the Database is still empty.
Here is my Code:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/spring/applicationContext.xml"})
#Transactional
#TransactionConfiguration(defaultRollback = true)
public class DaoTests {
#Autowired
private Repository repo;
#Autowired
private AccountService userService;
#Before
public void orgInstAccount() {
Organization o = new Organization();
o.setName("Organisation 1");
repo.saveEntity(o);
Institution i1 = new Institution();
i1.setName("xyz");
i1.setOwningOrganization(o);
repo.saveEntity(i1);
}
#Test(expected = DataIntegrityViolationException.class)
public void saveUserFail() {
Account user = new Account();
user.setAccountname("chz");
user.setPassword(userService.calcMD5Hash("123"));
user.setOwningInstitution(repo.getInstitutionByName("xyz"));
repo.saveEntity(user);
Assert.assertNotNull(repo.getAccountByName("chz"));
Account userNew = new Account();
userNew.setAccountname("chz");
userNew.setPassword(userService.calcMD5Hash("123"));
userNew.setOwningInstitution(repo.getInstitutionByName("xyz"));
repo.saveEntity(userNew);
//Here the Exception should be thrown but everything works fine.
}
}
The Repository Implementation is:
#Repository
#Transactional
#SuppressWarnings("unchecked")
public class RepositoryHibernateImpl implements Repository {
#Autowired
private SessionFactory factory;
#Override
public void saveEntity(Entity hce) {
factory.getCurrentSession().save(hce);
}
}
Maybe the Problem is because the Repository and the TestClass are marked with #Transactional?
Thank you in Advance.
Call flush() which will try to call sql immediatly instead of deferring it till transaction boundary
factory.getCurrentSession().flush()

Resources