Я пытаюсь использовать Spring Data, Hibernate Envers и аудит в приложении Spring Boot. Я настроил AuditorAwareImpl
public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("Default auditor");
}
}
и класс конфигурации для него.
@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class AuditingConfiguration {
@Bean
public AuditorAware<String> auditorProvider() {
return new AuditorAwareImpl();
}
}
Теперь я хотел бы создать AuditorAware для моих интеграционных тестов. Я создал новый класс конфигурации с аудитором теста
@Configuration
@Profile("test")
@EnableJpaAuditing(auditorAwareRef = "testAuditorProvider")
public class TestAuditingConfiguration {
@Bean
@Primary
public AuditorAware<String> testAuditorProvider() {
return () -> Optional.of("Test auditor");
}
}
И когда я пытаюсь написать свой интеграционный тест, как это
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class AuditingApplicationTests {
@Autowired
private AuditorAware<String> auditorAware;
@Autowired
private MovieRepository movieRepository;
@Test
public void testCurrentAuditor() {
String currentAuditor = auditorAware.getCurrentAuditor().get();
assertEquals("Test auditor", currentAuditor);
}
@Test
public void movieRepositoryTest() {
Movie movie = new Movie("Movie");
movieRepository.save(movie);
List<Movie> movies = movieRepository.findAll();
Movie result = movies.get(0);
assertEquals("Test auditor", result.getCreatedBy());
}
}
Я получаю эту ошибку:
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'jpaAuditingHandler' defined in null: Cannot register bean definition [Root bean: class [org.springframework.data.auditing.AuditingHandler]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'jpaAuditingHandler': There is already [Root bean: class [org.springframework.data.auditing.AuditingHandler]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
Когда я удаляю @EnableJpaAuditing
из TestAuditingConfiguration
, он отлично работает, за одним исключением - в тесте используется автонастройка auditorAware
- из TestAuditingConfiguration
, но с другой стороны для аудита используется AuditingConfiguration
, поэтому result.getCreatedBy()
будет вернуть Default auditor
вместо Test auditor
. Я прочитал, что для тестирования интеграции базы данных должна использоваться аннотация @DataJpaTest
, поэтому я изменил ее. Теперь с включенным @EnableJpaAuditing
на TestAuditingConfiguration
я получил:
org.springframework.beans.factory.UnsatisfiedDependencyException: Unsatisfied dependency expressed through field 'auditorAware'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.domain.AuditorAware<java.lang.String>' available: expected at least 1 bean which qualifies as autowire candidate
Но после добавления @Import(TestAuditingConfiguration.class)
все работает как я ожидал - result.getCreatedBy()
возвращает Test auditor
. Итак, наконец, мой тестовый класс выглядит так:
@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("test")
@Import(TestAuditingConfiguration.class)
public class AuditingApplicationTests {
@Autowired
private AuditorAware<String> auditorAware;
@Autowired
private MovieRepository movieRepository;
@Test
public void testCurrentAuditor() {
String currentAuditor = auditorAware.getCurrentAuditor().get();
assertEquals("Test auditor", currentAuditor);
}
@Test
public void movieRepositoryTest() {
Movie movie = new Movie("Movie");
movieRepository.save(movie);
List<Movie> movies = movieRepository.findAll();
Movie result = movies.get(0);
assertEquals("Test auditor", result.getCreatedBy());
}
}
Теперь я действительно запутался, как бины используются в определенных профилях и как работают @SpringBootTest
и @DataJpaTest
. И почему @Import
был важен для @DataJpaTest
? Может кто-нибудь объяснить мне, что и какой предпочтительный подход для тестирования базы данных?