如何测试春季交易

时间:2018-11-19 18:50:19

标签: spring spring-boot spring-data-jpa spring-data spring-transactions

我正在使用Spring Boot 2.1.0进行项目,并且遇到以下情况。

我有以下存储库

@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();
}

和以下组件

@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();
    }
}

现在,我想测试事务注释是否正常工作。

基本上,我的目标是检查在updateInProgressStatusAge()调用期间引发的runtimeException是否会导致updateNextStatusAge和updateBacklogStatusAge修改的回滚。

我该怎么做? 谢谢

2 个答案:

答案 0 :(得分:2)

您可以使用Mockito来通过使用@SpyBean或@MockBean来更改服务或存储库的行为。

不幸的是,@ SpyBean在JPA存储库上不起作用(https://github.com/spring-projects/spring-boot/issues/7033,此问题是针对Spring boot 1.4.1,但我对2.0.3.RELEASE也有同样的问题)

作为解决方法,您可以创建测试配置以手动创建模拟:

@Configuration
public class SpyRepositoryConfiguration {

   @Primary
   @Bean
   public ActivityRepository spyActivityRepository(final ActivityRepository real) 
      return Mockito.mock(ActivityRepository.class, AdditionalAnswers.delegatesTo(real));
   }
}

在测试中:

@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
}

答案 1 :(得分:0)

您可以更改方法以测试事务注释。

@Transactional
public void update() {
    activityRepository.updateBacklogStatusAge();
    activityRepository.updateNextStatusAge();
    throw Exception();
    activityRepository.updateInProgressStatusAge();
}

这将模拟您所需的情况。