问题描述
我有两个具有相同签名的bean。命名它们是为了获得正确的实例给请求它们的类。
@Configuration
public class MyConfiguration {
@Bean("durationForX")
public Duration durationForX() {
return Duration.ofSeconds(1);
}
@Bean("durationForY")
public Duration durationForY() {
return Duration.ofSeconds(5);
}
}
并用作
@Component
public class MyService {
public MyService(
@Qualifier("durationForX") duration
) {
...
}
}
和Y相似。
现在,我想在集成测试中自动装配上述bean的模型。我尝试了以下
@Configuration
@Profile("my-test-profile")
public class IntegrationTestConfiguration {
@Primary
@Bean("durationForX")
public Duration durationForXMock() {
return Duration.ofMillis(100);
}
@Primary
@Bean("durationForY")
public Duration durationForYMock() {
return Duration.ofMillis(500);
}
@Primary
@Bean
public AnotherService anotherService() {
// This one works as expected,probably because it is not a named bean
...
}
}
在运行集成测试时会导致错误消息
***************************
APPLICATION Failed TO START
***************************
Description:
The bean 'durationForX',defined in class path resource [com/../../MyConfiguration.class],Could not be registered. A bean with that name has already been defined in class path resource [com/.../.../IntegrationTestConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-deFinition-overriding=true
在集成测试中,我并不会自动装配实例本身,只有一个入口可以调用该应用程序。
@SpringBoottest(webEnvironment = SpringBoottest.WebEnvironment.DEFINED_PORT,classes = {MyApp.class})
@ActiveProfiles("it")
class MyIntegrationTest {
@Autowired
GraphQLTestTemplate graphQL;
...
}
我不太希望将bean覆盖设置为true,因为我想控制在哪里使用哪些bean。我希望模拟命名的bean遵循与未命名的bean相同的模式,这是为什么呢?有任何解决方法的想法吗?
解决方法
我建议使用其他配置文件进行测试,例如,您可以在主application.yml
中为主要应用程序定义值
application.yml
duration1:1
duration2:5
然后使用MyConfiguration
注释在@Value
类中阅读它们
@Configuration
public class MyConfiguration {
@Value("${duration1})
private Integer duration1;
@Value("${duration2})
private Integer duration2;
@Bean("durationForX")
public Duration durationForX() {
return Duration.ofSeconds(duration1);
}
@Bean("durationForY")
public Duration durationForY() {
return Duration.ofSeconds(duration2);
}
}
现在进行测试,在application-test.yml
或src/main/resources
下创建src/test/resources
,然后添加具有测试值的属性
application-test.yml
duration1:100
duration2:500
不需要任何IntegrationTestConfiguration
文件,您只需在test.yml
文件中维护测试属性
注意::请确保使用@Profile("test")
和@SpringBootTest
注释测试类以加载具有相应测试属性的测试应用程序复制上下文。
@SpringBootTest
@Profile("test)
public class AppTest {
}