首页 > 解决方案 > 配置覆盖默认应用程序上下文 bean 的 Spring 的 @DataJpaTest

问题描述

我正在为我的@DataJpaTest 配置而苦苦挣扎。我想利用@DataJpaTest 提供的自动配置的spring 上下文,但我想覆盖它的一些bean。

这是我的主要课程:

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"));
        };
    }

如您所见,我为 CommandLineRunner 提供了依赖于某些服务的实现。

我也有一个测试:

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

当我运行测试时,我收到以下错误:

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: {}

这很有意义!自动配置的测试只为上下文的“切片”提供实现。显然缺少 BookInputPort 的实现。我在测试上下文中不需要这个 commandLineRunner。我创建了一个不依赖于任何服务的 commandLineRunner。我可以尝试通过添加到我的测试类嵌套类来解决这个问题:

@TestConfiguration
    static class BookRepositoryTestConfiguration {

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

这样就解决了问题。有点儿。如果我有更多这样的测试,我将不得不将此嵌套类复制粘贴到每个测试类。这不是最佳解决方案。我试图将其外部化为可以由以下配置导入@Import 的配置:这是配置类:

@Configuration
public class MyTestConfiguration {

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

但随后应用程序失败并显示一条消息:

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

在这种情况下,我检查了该错误和其他人在 SO 上的建议:

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

我这样做了,我得到了:

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: {}

这与我开始的问题完全相同。我采取了所有这些步骤,发现自己处于最初的位置。

你知道如何解决这个问题吗?我没有模糊的想法或线索。

标签: javaspringspring-bootintegration-testing

解决方案


@DataJpaTest generally starts scanning from current package of the test class and scans upwards till it finds the class annotated with @SpringBootConfiguration.

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.

@SpringBootConfiguration
@EnableAutoConfiguration
public class TestRepositoryConfig {

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

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

}

推荐阅读