#spring-boot #spring-data-jpa #lifecycle #applicationcontext
#весенняя загрузка #spring-data-jpa #жизненный цикл #applicationcontext
Вопрос:
Я использую @DataJpaTest для проверки функциональности моих репозиториев (весенняя редакция данных). Все работало нормально, пока я не изменил функциональность в объектах, которые нужно сохранить. У меня есть методы обратного вызова (@prePersist и @preUpdate), для которых требуется текущий пользователь изменения. Я определяю пользователя с помощью SecurityContext и в качестве запасного варианта из моих ConfigurationProperties. Сущность кодируется следующим образом.
@PrePersist
public void onCreation() {
final String user = KVLUserProvider.ermittleAngemeldetenUserMitFallback();
this.erstellungsCcid = user;
this.veraenderungsCcid = user;
final LocalDateTime time = ZeitHelper.jetzt();
this.erstellungsZeitpunkt = time;
this.veraenderungsZeitpunkt = time;
}
@PreUpdate
public void onModification() {
LocalDateTime zpAlt = this.veraenderungsZeitpunkt;
this.veraenderungsCcid = KVLUserProvider.ermittleAngemeldetenUserMitFallback();
this.veraenderungsZeitpunkt = ZeitHelper.jetzt();
logger.trace("onModification {} {} vorher {} nachher {}", this.getClass().getSimpleName(), this.getId(), zpAlt, veraenderungsZeitpunkt);
}
KVLUserProvider выглядит следующим образом.
private KVLUserProvider(){}
public static String ermittleAngemeldetenUserMitFallback() {
String user = Optional
.of(SecurityContextHolder.getContext().getAuthentication() != null ?
SecurityContextHolder.getContext().getAuthentication().getName() : null)
.orElse(ApplicationContextProvider.getApplicationContext()
.getBean(KVLProperties.class).getTechnischerUser());
logger.debug("Der KVLUserProvider hat folgenden User ermittelt: {}", user);
return user;
}
Проблема возникает в упомянутом выше классе, где я пытаюсь получить ApplicationContext с помощью ApplicationContextProvider . Поставщик реализует интерфейс ApplicationContextAware, который заставляет Spring Boot вызывать метод setAppicationConext в реализующем классе. Для полноты здесь также есть ApplicationContextProvider .
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContextProvider instance;
private ApplicationContextProvider() {
}
private ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
if (instance == null) {
throw new RuntimeException("ApplicationContext has not been injected yet!");
}
return instance.applicationContext;
}
private static void setProviderInstance(ApplicationContextProvider provider) {
instance = provider;
}
@Override
public void setApplicationContext(ApplicationContext acx) throws BeansException {
applicationContext = acx;
setProviderInstance(this);
}
}
Вопрос в том, чего не хватает в @DataJpaTest для вызова метода setApplicationContext, как это делает SpringBootTest перед фазой предварительной инициализации жизненного цикла? Есть ли какой-то @Enable… Аннотация для достижения этой цели?
Тест выглядит следующим образом.
@SpringBootTest
//@DataJpaTest
//@AutoConfigureJdbc
//@Import(DatabaseConfig.class)
@WithMockUser
@SpringBootTest
class Test {
@Autowired
private ARepository aRepository;
@Autowired
private ZRepository zRepository;
@Test
void testSaveUndUpdateA() {
Z z = new Z();
final Z savedZ = zRepository.save(z);
assertThat(savedZahlungsInformation).isNotNull();
A a = ABuilder.get(savedZ).build();
final A savedA = aRepository.save(a);
assertThat(savedA).isNotNull();
savedA.setZBetrag(BigDecimal.TEN);
aRepository.save(auszahlung);
final Optional<A> actual = Repository.findById(savedA.getId());
assertThat(actual).isPresent();
assertThat(actual.get().getId()).isEqualTo(z.getId());
assertThat(actual.get().getZBetrag()).isEqualTo(BigDecimal.TEN.setScale(2, RoundingMode.UNNECESSARY));
}
Тест зеленый, потому что я изменил его на SpringBootTest. До моего изменения это был DataJpaTest, и пользователь был предоставлен другим способом.
Когда я запускаю тест как da DataJpaTest, он завершается с ошибкой, потому что отсутствует ApplicationContext.
с уважением.
Комментарии:
1. другим вариантом может быть использование AuditorAware
Ответ №1:
если ошибка была «ApplicationContext еще не введен!»
попробуйте добавить поверх Test
класса
@Import({ApplicationContextProvider.class})
если после этого вы получите сообщение об ошибке «NoSuchBeanDefinition: нет подходящего компонента типа «…Доступны свойства KVLProperties», также добавьте свойства KVLProperties в аннотацию
@Import({ApplicationContextProvider.class, KVLProperties.class})