[英]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.