【发布时间】:2022-01-14 10:36:57
【问题描述】:
我正在使用@DataJpaTest 来测试我的(春季数据修订)存储库的功能。在我更改要保存的实体中的功能之前,一切正常。 我有需要更改的 currentUser 的回调方法(@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;
}
问题发生在上面提到的类中,我试图通过 ApplicationContextProvider 获取 ApplicationContext。 Provider 实现了 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 在生命周期的 PreInitialization 阶段之前调用 setApplicationContext 方法的缺失部分是什么?有没有一种@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。
亲切的问候。
【问题讨论】:
-
另一种选择是使用AuditorAware
标签: spring-boot spring-data-jpa lifecycle applicationcontext