简体   繁体   English

Jpa审计的测试配置

[英]Test configuration for Jpa auditing

I am trying to use Spring Data, Hibernate Envers and auditing in Spring Boot application.我正在尝试在 Spring Boot 应用程序中使用 Spring Data、Hibernate Envers 和审计。 I have configured AuditorAwareImpl我已经配置了 AuditorAwareImpl

public class AuditorAwareImpl implements AuditorAware<String> {

    @Override
    public Optional<String> getCurrentAuditor() {
        return Optional.of("Default auditor");
    }
}

and configuration class for it.和它的配置类。

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class AuditingConfiguration {

    @Bean
    public AuditorAware<String> auditorProvider() {
        return new AuditorAwareImpl();
    }
}

Now I would like to create AuditorAware for my Integration tests.现在我想为我的集成测试创建 AuditorAware。 I have created new configuration class with test auditor我用测试审计员创建了新的配置类

@Configuration
@Profile("test")
@EnableJpaAuditing(auditorAwareRef = "testAuditorProvider")
public class TestAuditingConfiguration {

    @Bean
    @Primary
    public AuditorAware<String> testAuditorProvider() {
        return () -> Optional.of("Test auditor");
    }

}

And when I try to write my integration test like this当我尝试像这样编写集成测试时

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

I am getting this error:我收到此错误:

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.

When I remove @EnableJpaAuditing from TestAuditingConfiguration it works fine with one exception - autowired auditorAware in test is one from TestAuditingConfiguration but on the other hand for auditing is used from AuditingConfiguration so result.getCreatedBy() will return Default auditor instead of Test auditor .当我从TestAuditingConfiguration删除@EnableJpaAuditing ,它可以正常工作,但有一个例外 - 测试中的自动装配auditorAware是来自TestAuditingConfiguration一个,但另一方面用于审计是从AuditingConfiguration使用的,因此result.getCreatedBy()将返回Default auditor result.getCreatedBy()而不是Test auditor result.getCreatedBy() I read that for database integration tests should be used @DataJpaTest annotation so I have changed it.我读到数据库集成测试应该使用@DataJpaTest注释,所以我已经改变了它。 Now with enabled @EnableJpaAuditing on TestAuditingConfiguration I received:现在在@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

But after adding @Import(TestAuditingConfiguration.class) it works as I excpected - result.getCreatedBy() returns Test auditor .但是在添加@Import(TestAuditingConfiguration.class)它按我的预期工作 - result.getCreatedBy()返回Test auditor result.getCreatedBy() So finally my test class looks like:所以最后我的测试类看起来像:

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

}

Now I am really confused how beans are used in specific profiles and how @SpringBootTest and @DataJpaTest works.现在我真的很困惑 bean 在特定配置文件中的使用方式以及@SpringBootTest@DataJpaTest工作原理。 And why @Import was important for @DataJpaTest ?为什么@Import是重要的@DataJpaTest Can anyone explain me that and what is preferred approach for database testing?谁能向我解释一下,什么是数据库测试的首选方法?

@DataJpaTest is just a shortcut for a bunch of annotations. @DataJpaTest只是一堆注释的快捷方式。 See https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/orm/jpa/DataJpaTest.htmlhttps://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/orm/jpa/DataJpaTest.html

It basically creates an ApplicationContext with only those beans regsitered that are relevant for JPA and Spring Data JPA.它基本上创建了一个 ApplicationContext,其中只包含与 JPA 和 Spring Data JPA 相关的那些 bean。

@SpringBootTest creates a complete ApplicationContext with everything that is in your application. @SpringBootTest使用应用程序中的所有内容创建一个完整的 ApplicationContext。 A lot of which it finds by scanning the class path for classes annotated with @Configuration .它通过扫描用@Configuration注释的类的类路径来找到很多。

Therefore it will contain more "stuff" and in your case two @AuditorAware beans.因此,它将包含更多“东西”,在您的情况下将包含两个@AuditorAware bean。 Which some "magic" inside Spring tries to create a jpaAuditingHandler bean from. Spring 内部的一些“魔法”试图从中创建一个jpaAuditingHandler bean。 Since there are two AuditorAware beans we end up with two beans of same name which is not acceptable.由于有两个AuditorAware bean,我们最终会得到两个同名的 bean,这是不可接受的。 See Spring boot 2.1 bean override vs. Primary .请参阅Spring boot 2.1 bean override vs. Primary You Probably could enable bean overriding but that is not recommended.您可能可以启用 bean 覆盖,但不建议这样做。

With @DataJpaTest these configurations are not found and you end up with no AuditorAware bean at all.使用@DataJpaTest这些配置,最终您根本没有AuditorAware bean。 By importing the right configuration you get exactly the bean you want for your test and everything is happy.通过导入正确的配置,您可以准确地获得测试所需的 bean,一切都很顺利。

Which one is the better approach depends on how you run your tests and in the end is probably mostly a matter of taste.哪种方法更好取决于您如何运行测试,最终可能主要是品味问题。

I prefer using @DataJpaTest for real systems, because it limits the effect of unrelated configurations on the database test.我更喜欢将@DataJpaTest用于真实系统,因为它限制了无关配置对数据库测试的影响。 It might also execute slightly faster although that is probably hardly noticeable for most test suites because in most applications I work with, most of the startup time was eaten by Hibernate which is required for database tests anyway and when you run multiple test having different configurations for different tests negatively affects caching.它的执行速度也可能稍快一些,尽管这对于大多数测试套件来说可能几乎不明显,因为在我使用的大多数应用程序中,大部分启动时间都被 Hibernate 占用了不同的测试会对缓存产生负面影响。

For small projects I prefer @SpringBootTest since it is less to write and makes things simpler at least in the simple cases.对于小型项目,我更喜欢@SpringBootTest因为它编写起来更少,至少在简单的情况下使事情变得更简单。

move @EnableJpaAuditing on another new file另一个新文件上移动@EnableJpaAuditing

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration
@EnableJpaAuditing
public class JpaConfiguration {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM