DataJpaTest против SpringBootTest

#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})