[英]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如何在一个环境而不是另一个环境中加载特定实体
@Profile
annotation in your entities.@Profile
注释。@Profile({"prod"})
on entities/services you don't want to load in test run, and@Profile({"prod"})
放在您不想在测试运行中加载的实体/服务上,并且@Profile({"prod", "test"})
on entities/services you want to load in both test
and prod
environmentsprod
@Profile({"prod", "test"})
放在要在test
和生产环境中加载的实体/服务上test
with test
profile.test
配置文件运行test
。 It will not load unnecessary entities
.entities
。@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.