【发布时间】:2020-05-17 17:57:57
【问题描述】:
我正在为我的@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
我检查了这个错误和其他人在这种情况下的建议:
@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: {}
这与我一开始的问题完全相同。 我采取了所有这些步骤,发现自己回到了最初的位置。
你知道如何解决这个问题吗?我没有模糊的想法或线索。
【问题讨论】:
-
为什么要在测试类中添加运行器?主要跑步者还可以。它将在测试上下文中运行
-
@muasif80 是的,运行器在测试上下文中运行。这正是问题所在。主类中的 Runner 实现需要未在测试上下文中创建的服务(自动配置的测试,如 DataJpaTest 或 WebMvcTest 仅创建原始上下文的一部分,而没有使用 Service 或 Component 注释的类 - 如 spring 文档中所述。在这种情况下,测试应用程序上下文无法由于在主类中缺少 CommandLineRunner impl 中的 BookInputPort 而启动。这会导致上下文失败并导致测试失败。
标签: java spring spring-boot integration-testing