Как использовать Spring defaultValidator в тестах JUnit

#spring #spring-boot

#весна #пружинный ботинок #пружинное испытание #тест на пружинную загрузку

Вопрос:

Я использовал @SpringJunitConfig в своих тестовых классах, чтобы сократить время загрузки контекста @SpringBootTest . Это хорошо работало, когда я использовал только свои собственные классы, так как я могу легко указать пакеты / классы, которые будут загружены.

Теперь я пытаюсь использовать проверку аргументов Spring по умолчанию. Основываясь на других ответах SO, я создал и загрузил defaultValidator боб. Однако проверка Spring по умолчанию не запускается, когда мои тесты вызывают метод с проверками, и тест завершается неудачно. Я знаю, что аннотации к тестируемому классу верны, потому что, когда я переключаюсь на @SpringBootTest тест, он проходит.

Есть какие-нибудь дополнительные идеи?

Это самое близкое, к чему я подошел, но автоматическая проверка весной не выполняется, если я не переключусь на @SpringBootTest то, что загружает полный контекст и работает слишком медленно.

Тестовый класс

 @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, () -gt; {  userService.findUser(null); // null  });  }  

Класс обслуживания

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

Комментарии:

1. @xerx593 да. Добавлен класс обслуживания к вопросу.

2. вообще никаких (ожидаемых) исключений? или не того типа? (какова точная причина сбоя теста?)

Ответ №1:

defaultValidator Компонент определяется функцией автоматической настройки spring-boot, которая будет включена, если есть какие-либо @Configuration компоненты с аннотациями @EnableAutoConfiguration .

Но @EnableAutoConfiguration по умолчанию будут рассмотрены все параметры автоматической настройки, определенные spring-boot (т. Е. те, которые определены в spring.factories ), которых может быть слишком много для написания модульного теста. Таким образом, есть еще одна аннотация, @ImportAutoConfiguration которая может просто импортировать и применять указанный класс автоматической настройки.

Поскольку defaultValidator компонент определен в 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();  }  }   }  

Советы : Чтобы узнать , какой класс автоматической настройки определяет defaultValidator компонент, вы можете включить режим отладки в application.properties :

 debug=true  

затем запустите приложение весенней загрузки как обычно, и оно распечатает отчет об оценке следующих условий :

 ============================ 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)  

Комментарии:

1. Отличный ответ, особенно Совет, так как он помогает мне лучше понять, как решить подобные проблемы в будущем!