首页 > 解决方案 > 如何测试 Spring 事务

问题描述

我正在使用 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 修改的回滚。

我怎样才能做到这一点?谢谢

标签: springspring-bootspring-data-jpaspring-dataspring-transactions

解决方案


您可以使用 Mockito 来更改服务或存储库的行为,方法是使用 @SpyBean 或 @MockBean。

不幸的是,@SpyBean 不适用于 JPA 存储库(https://github.com/spring-projects/spring-boot/issues/7033,这个问题适用于 Spring boot 1.4.1,但我对 2.0.3 也有同样的问题。发布)

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

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

推荐阅读