簡體   English   中英

如何在 JUnit 測試中使用 Spring defaultValidator

[英]How to use Spring defaultValidator in JUnit tests

我一直在我的測試類上使用@SpringJunitConfig來減少@SpringBootTest的上下文加載時間。 當我只使用我自己的類時,這很有效,因為我可以輕松地指定要加載的包/類。

現在我正在嘗試使用 Spring 的默認參數驗證。 基於其他 SO 答案,我創建並加載了defaultValidator bean。 但是,當我的測試調用帶有驗證的方法並且測試失敗時,不會觸發 Spring 的默認驗證。 我知道正在測試的 class 上的注釋是正確的,因為當我切換到@SpringBootTest時,測試通過了。

有什么額外的想法嗎?

這是我最接近的一次,但不會發生 Spring 的自動驗證,除非我切換到加載完整上下文且速度太慢的@SpringBootTest

測試 Class

@SpringJUnitConfig()
class UserServiceImplTest {
    @Configuration
    @ComponentScan(basePackages = { "com.user" },
            includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { UserMapper.class,
                    UserServiceImpl.class}), useDefaultFilters = false)
    static class ConfigMe {
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Bean
        public Validator defaultValidator() {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            return factory.getValidator();
        }
    }

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private UserMapper mapper;

    @Autowired
    @Qualifier("defaultValidator")
    Validator validator;

    @MockBean
    private UserDao userDao;

    // tests for UserServiceImpl that require valdiation of method arguments
    // e.g. public UserDto findUser(@NotNull @Size(min = 30, max = 30) String userUnique)

    @Test
    void givenInvalidUnique_whenFind_thenConstraintException() {
        assertThrows(ConstraintViolationException.class, () -> {
            userService.findUser(null); // null
        });
    }

服務 Class

@Service
@Transactional
@Validated
public class UserServiceImpl implements UserService {

    @Override
    @Transactional(readOnly = true)
    public UserDto findUser(@NotNull @Size(min = 30, max = 30) String userUnique) {
        log.trace("findUser called with unique [{}]", userUnique);
        Optional<User> foundUser = userDao.findByUserUnique(userUnique);
        if (foundUser.isEmpty())
            throw new MyEntityNotFoundException(String.format("Could not find user with unique of [%s]", userUnique));

        return mapper.UserEntityToDto(foundUser.get());
    }
    
    // other service methods
}

defaultValidator bean 由 spring-boot 自動配置內容定義,如果有任何帶有@EnableAutoConfiguration注釋的@Configuration bean,它將啟用。

但是@EnableAutoConfiguration默認會考慮所有由 spring-boot 定義的自動配置內容(即在spring.factories中定義的那些),這對於編寫單元測試來說可能太多了。 因此,還有另一個名為@ImportAutoConfiguration的注釋可以導入和應用指定的自動配置 class。

由於defaultValidator bean 是在ValidationAutoConfiguration中定義的,這意味着您可以通過以下方式簡單地導入它:

@SpringJUnitConfig
class UserServiceImplTest {

    @Configuration
    @ComponentScan(basePackages = { "com.user" }, includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { UserMapper.class, UserServiceImpl.class}), useDefaultFilters = false)
    @ImportAutoConfiguration(ValidationAutoConfiguration.class)                
    static class ConfigMe {
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }

 }

提示:要找出哪個自動配置 class 定義了defaultValidator bean,您可以在application.properties中啟用調試模式:

debug=true

然后像往常一樣啟動 spring-boot 應用程序,它將打印出以下條件評估報告:

============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:
-----------------

   ValidationAutoConfiguration matched:
      - @ConditionalOnClass found required class 'javax.validation.executable.ExecutableValidator' (OnClassCondition)
      - @ConditionalOnResource found location classpath:META-INF/services/javax.validation.spi.ValidationProvider (OnResourceCondition)

   ValidationAutoConfiguration#defaultValidator matched:
      - @ConditionalOnMissingBean (types: javax.validation.Validator; SearchStrategy: all) did not find any beans (OnBeanCondition)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM