简体   繁体   English

配置覆盖默认应用程序上下文 bean 的 Spring 的 @DataJpaTest

[英]Configuring Spring's @DataJpaTest that overrides default application context beans

I'm struggling with configuration for my @DataJpaTest.我正在为我的@DataJpaTest 配置而苦苦挣扎。 I'd like to take advantage of auto-configured spring context provided by @DataJpaTest, but I'd like to override some of it's beans.我想利用@DataJpaTest 提供的自动配置的 spring 上下文,但我想覆盖其中的一些 bean。

This is my main class:这是我的主 class:

public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(BookInputPort bookInputPort) {
        return args -> {
            bookInputPort.addNewBook(new BookDto("ABC", "DEF"));
            bookInputPort.addNewBook(new BookDto("GHI", "JKL"));
            bookInputPort.addNewBook(new BookDto("MNO", "PRS"));
        };
    }

As you can clearly see, I provide my implementation for CommandLineRunner that depends on some service.您可以清楚地看到,我为依赖于某些服务的 CommandLineRunner 提供了我的实现。

I also have a test:我也有一个测试:

@DataJpaTest
public class BookRepositoryTest {

    public static final String TITLE = "For whom the bell tolls";
    public static final String AUTHOR = "Hemingway";

    @Autowired
    private BookRepository bookRepository;

    @Test
    public void testRepository() {
        Book save = bookRepository.save(new Book(TITLE, AUTHOR));
        assertEquals(TITLE, save.getTitle());
        assertEquals(AUTHOR, save.getAuthor());
    }
}

When I run the test I get the following error:当我运行测试时,出现以下错误:

No qualifying bean of type 'com.example.demo.domain.book.ports.BookInputPort' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

That makes perfect sense.这是完全有道理的。 Auto-configured test provides implementation only for a 'slice' of the context.自动配置的测试仅为上下文的“切片”提供实现。 Apparently implementation of BookInputPort is missing.显然缺少 BookInputPort 的实现。 I do not need this commandLineRunner in a test context.我在测试环境中不需要这个 commandLineRunner。 I get create a commandLineRunner that does not depend on any service: I can try to solve the issue by adding to my test class nested class :我创建了一个不依赖于任何服务的 commandLineRunner:我可以尝试通过添加到我的测试 class 嵌套 class 来解决问题:

@TestConfiguration
    static class BookRepositoryTestConfiguration {

        @Bean
        CommandLineRunner commandLineRunner() {
            return args -> {
            };
        }
    }

That solves the problem.这解决了问题。 Kind of.有点儿。 If I had more tests like this I would have to copy-paste this nested class to each test class. It's not an optimal solution.如果我有更多这样的测试,我将不得不将这个嵌套的 class 复制粘贴到每个测试 class。这不是最佳解决方案。 I tried to externalize this to a configuration that could be imported by @Import This is the config class:我试图将其外部化为可以通过@Import导入的配置这是配置 class:

@Configuration
public class MyTestConfiguration {

    @Bean
    public CommandLineRunner commandLineRunner() {
        return args -> {
        };
    }
}

But then the application fails with a message:但是随后应用程序失败并显示一条消息:

Invalid bean definition with name 'commandLineRunner' defined in com.example.demo.DemoApplication: Cannot register bean definition

I checked that error and other folks on SO suggested in this case:在这种情况下,我检查了该错误和 SO 上的其他人建议:

@DataJpaTest(properties = "spring.main.allow-bean-definition-overriding=true")

I did that and I got:我这样做了,我得到了:

No qualifying bean of type 'com.example.demo.domain.book.ports.BookInputPort' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

That is exactly the same problem I started with.这与我开始时遇到的问题完全相同。 I took all these steps and found myself in the place where I was at the very beginning.我采取了所有这些步骤,发现自己回到了最开始的地方。

Do you have any idea how to solve this issue?你知道如何解决这个问题吗? I do not have a vague idea or clue.我没有一个模糊的想法或线索。

@DataJpaTest generally starts scanning from current package of the test class and scans upwards till it finds the class annotated with @SpringBootConfiguration. @DataJpaTest一般从测试class的当前package开始扫描,向上扫描,直到找到@SpringBootConfiguration注解的class。

So creating a SpringBootConfiguration class at the repository root package will create only beans defined within that package. On top of that we can add any customized test bean required for our test class in that configuration class.因此,在存储库根目录 package 中创建 SpringBootConfiguration class 将仅创建在该 package 中定义的 bean。最重要的是,我们可以在该配置 class 中添加测试 class 所需的任何自定义测试 bean。

@SpringBootConfiguration
@EnableAutoConfiguration
public class TestRepositoryConfig {

    @Bean
    public CommandLineRunner commandLineRunner() {
        return args -> {
        };
    }

    @Bean
    public BookInputPort bootInputPort(){
        return new BookInputPort();
    }

}

In Spring Boot test class you can do it like this在 Spring 启动测试 class 你可以这样做

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class YourClassTest {

    @Autowired
    private YourService yourService;

It does load all the services and I am using it perfectly fine它确实加载了所有服务,我使用它非常好

How to load specific entities in one environment and not the other如何在一个环境而不是另一个环境中加载特定实体

  1. You can use @Profile annotation in your entities.您可以在您的实体中使用@Profile注释。
  2. Put @Profile({"prod"}) on entities/services you don't want to load in test run, and@Profile({"prod"})放在您不想在测试运行中加载的实体/服务上,并且
  3. Put @Profile({"prod", "test"}) on entities/services you want to load in both test and prod environments将 @Profile({" prod @Profile({"prod", "test"})放在要在test和生产环境中加载的实体/服务上
  4. Then run the test with test profile.然后使用test配置文件运行test It will not load unnecessary entities .它不会加载不必要的entities
  5. You can put @Profile annotation on other services too.您也可以在其他服务上放置@Profile注释。

The annotation @DataJpaTest only loads the JPA part of a Spring Boot application, the application context might not loaded because you have @DataJpaTest annotation. @DataJpaTest注释仅加载 Spring 启动应用程序的 JPA 部分,应用程序上下文可能未加载,因为您有@DataJpaTest注释。 Try to replace the @DataJpaTest with @SpringBootTest .尝试用@DataJpaTest替换@SpringBootTest

As per Spring documentation :根据Spring 文档

By default, tests annotated with @DataJpaTest will use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource).默认情况下,用@DataJpaTest注释的测试将使用嵌入式内存数据库(替换任何显式或通常自动配置的数据源)。 The @AutoConfigureTestDatabase annotation can be used to override these settings. @AutoConfigureTestDatabase注释可用于覆盖这些设置。 If you are looking to load your full application configuration, but use an embedded database, you should consider @SpringBootTest combined with @AutoConfigureTestDatabase rather than this annotation.如果您希望加载完整的应用程序配置,但使用嵌入式数据库,则应考虑将@SpringBootTest @AutoConfigureTestDatabase使用,而不是使用此注释。

暂无
暂无

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

相关问题 春天-应用程序上下文中的bean是否动态绑定到PropertyPlaceholderConfigurer? - spring — are beans in application context binded to PropertyPlaceholderConfigurer dynamically? 以编程方式将Bean添加到Spring应用程序上下文 - Programmatically adding Beans to Spring application Context 配置Spring bean - Configuring Spring beans 在测试期间初始化应用程序上下文,不包括 spring 集成 bean - Initialize application context during testing excluding the spring integration beans 应用上下文中一些bean的依赖形成了一个循环:在spring boot - The dependencies of some of the beans in the application context form a cycle: in spring boot 应用程序启动后在Spring上下文中初始化bean的最佳方法是什么? - Best way to initialize beans in Spring context after application started? Spring boot 应用上下文中一些bean的依赖形成了一个循环: - Spring boot The dependencies of some of the beans in the application context form a cycle: 应用上下文中部分bean的依赖在Spring批处理中形成循环 - The dependencies of some of the beans in the application context form a cycle in Spring Batch Spring Boot 1.5.1和“应用程序上下文中某些Bean的依赖性形成一个循环” - Spring Boot 1.5.1 and “The dependencies of some of the beans in the application context form a cycle” 使用带有应用程序上下文bean的Spring EL评估bean表达式 - Evaluate a bean expression with Spring EL with application context beans
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM