Here is a test class:
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
public class ValidationTest {
@Autowired
private EntityManager entityManager
...
}
I would like to test the service:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isEmailUnique(String emailAddress) {
Optional<User> user = userRepository.findByEmail(emailAddress);
...
}
So to do it I create and save an entity:
entityManager.persist(new User(name: "abc", email: "[email protected]"))
entityManager.flush()
and finally calling the request:
mockMvc.perform(post("..."))
What am I missing that the userRepository.findByEmail()
does not see an inserted entity?
ps: if I remove the @Transactional
from the method then the test works fine.
The environment you act in is difficult to understand because you only provide some excerpts! But from what I see I would guess that...
If you annotate your test with @Transactional
, every test method is surrounded with a new transaction that is automatically rolled back after the test method is executed.
If you now prepare some data in your test method it is visible in the scope of the implicit created transaction. If you then call your service method and this service method wants to have a new transaction, this new transaction does not 'see' the data you prepared in the outer transaction. If you remove the @Transactional
annotation from the service method, the repository can now 'see' the data.
If you have a look into the javadoc of the Propagation
enum, you will see that PROPAGATION_REQUIRES_NEW
is described the following way:
Create a new transaction, and suspend the current transaction if one exists.
The question is, why do they necessarily need a new transaction even if one already exists? Can't they just create a new one if none is available yet, but use the existing one if one already exists? That would be the case with the SUPPORTS
propagation, that is configured by default on the @Transactional
annotation.