Reputation: 1488
I'm working to a project with Spring Boot 2.1.0 and I've the following situation.
I've the following repository
@Repository
public interface ActivityRepository extends PagingAndSortingRepository<Activity, Long> {
@Transactional
@Modifying
@Query("") // Imagine a query
void updateBacklogStatusAge();
@Transactional
@Modifying
@Query("QUERY 2") // Imagine a query
void updateNextStatusAge();
@Transactional
@Modifying
@Query("QUERY 3") // Imagine a query
void updateInProgressStatusAge();
}
and the following component
@Component
public class ColumnAgeJob {
private final ActivityRepository activityRepository;
public ColumnAgeJob(final ActivityRepository pActivityRepository) {
activityRepository = pActivityRepository;
}
@Transactional
public void update() {
activityRepository.updateBacklogStatusAge();
activityRepository.updateNextStatusAge();
activityRepository.updateInProgressStatusAge();
}
}
Now I want to test if the transactional annotation is working.
Basically my goal is to check if a runtimeException raised during the updateInProgressStatusAge() call will cause a rollback of updateNextStatusAge and updateBacklogStatusAge modifications.
How can I do that? Thank you
Upvotes: 3
Views: 6663
Reputation: 76
You can use Mockito in order to change the behaviour of your service or repository by using @SpyBean or @MockBean.
Unfortunately @SpyBean do not works on JPA repository (https://github.com/spring-projects/spring-boot/issues/7033, this issue is for Spring boot 1.4.1, but I have the same problem with 2.0.3.RELEASE)
As workaround you can create a test configuration to create manually your mock:
@Configuration
public class SpyRepositoryConfiguration {
@Primary
@Bean
public ActivityRepository spyActivityRepository(final ActivityRepository real)
return Mockito.mock(ActivityRepository.class, AdditionalAnswers.delegatesTo(real));
}
}
And in your test:
@Autowired
private ActivityRepository activityRepository;
....
@Test
public void testTransactional() {
Mockito.doThrow(new ConstraintViolationException(Collections.emptySet())).when(activityRepository).updateInProgressStatusAge();
activityRepository.updateBacklogStatusAge();
activityRepository.updateNextStatusAge();
activityRepository.updateInProgressStatusAge();
// verify that rollback happens
}
Upvotes: 5
Reputation: 365
You can change your method to test your transactional annotation.
@Transactional
public void update() {
activityRepository.updateBacklogStatusAge();
activityRepository.updateNextStatusAge();
throw Exception();
activityRepository.updateInProgressStatusAge();
}
This will simulate your desired scenario.
Upvotes: 0