jwi*_*ner 8 java junit spring unit-testing spring-java-config
我一直在遇到测试类的@ComponentScan问题@Configuration- 也就是说,在集成测试期间会@ComponentScan出现意外@Configuration情况.
例如,假设您有一些全局配置,src/main/java其中包含组件com.example.service,com.example.config.GlobalConfiguration:
package com.example.config;
...
@Configuration
@ComponentScan(basePackageClasses = ServiceA.class)
public class GlobalConfiguration {
...
}
Run Code Online (Sandbox Code Playgroud)
它旨在提供两个服务,com.example.services.ServiceA并com.example.services.ServiceB注释@Component和@Profile("!test")(为简洁起见省略).
然后在src/test/java中,com.example.services.ServiceATest:
package com.example.services;
...
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ServiceATest.ServiceATestConfiguration.class)
public class ServiceATest {
...
@Configuration
public static class ServiceATestConfiguration {
@Bean
public ServiceA serviceA() {
return ServiceA(somemocking...);
}
}
}
Run Code Online (Sandbox Code Playgroud)
而且com.example.ServiceBIntegrationTest,GlobalConfiguration.class为了进行集成测试需要引入,但仍然避免使用@ActiveProfiles("test")以下方法引入危险的实现:
package com.example.services;
...
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(classes = {GlobalConfiguration.class, ServiceBIntegrationTest.ServiceBIntegrationTestConfiguration.class})
public class ServiceBIntegrationTest {
...
@Configuration
public static class ServiceBIntegrationTestConfiguration {
@Bean
public ServiceB serviceB() {
return ServiceB(somemocking...);
}
}
}
Run Code Online (Sandbox Code Playgroud)
明显的意图ServiceBIntegrationTest是通过引入完整的src/main/java应用程序配置GlobalConfiguration,排除危险组件@ActiveProfiles("test")并用自己的实现替换那些被排除的组件.然而,在测试的命名空间src/main/java和src/test/java组合,这样GlobalConfiguration的 @ComponentScan发现多在classpath中比正常情况-即ServiceA在规定豆ServiceA.ServiceATestConfiguration.这很容易导致冲突和意外结果.
现在,你可以做的东西GlobalConfiguration一样@ComponentScan(..., excludeFilters= @ComponentScan.Filter(type = FilterType.REGEX, pattern = "\\.*(T|t)est\\.*")),但都有自己的问题.依赖命名约定非常脆弱; 尽管如此,即使您退出了@TestConfiguration注释并使用了注释FilterType.ANNOTATION,您也可以有效地让您src/main/java了解自己src/test/java,而不应该是IMO(请参阅下面的注释).
就目前而言,我已经通过使用其他配置文件解决了我的问题.在ServiceA,我添加一个唯一的配置文件名称 - 以便其配置文件注释变得类似@ActiveProfiles("test,serviceatest").然后,在ServiceATest.ServiceATestConfiguration我添加注释@Profile("serviceatest").这有效地限制了ServiceATestConfiguration开销相对较小的范围,但似乎要么:
a)我使用@ComponentScan不正确,或
b)应该有一个更清洁的模式来处理这个问题
这是什么?
注意:是的,该应用程序是测试感知的,因为它正在使用@Profile("!test"),但我认为使应用程序具有轻微的测试意识,以防止不正确的资源使用并使其具有测试感知,以确保测试的正确性是非常不同的事情.
我发现您在集成测试期间试图伪造 Spring bean。如果您将注释@Profile与注释结合起来,那么您的大部分头痛都会消失,并且您不需要使用 来标记生产 bean 。@ActiveProfiles@Primary@Profile("!test")
对评论的反应:
按封装结构。组件扫描扫描当前包和子包内的所有包。如果您不想扫描 bean,只需修改您的包结构,使 bean 不在您的组件扫描范围内。
Spring 不区分包和src/test/java或src/main/java。试图排除带有@Profile("!test")设计气味的生产豆。你应该避免它。我建议给一个从提到的博客进行接触的机会。
请注意,当您使用 @Primary 注释覆盖 bean 时,您可能需要使用@DirtiesContext注释来为其他测试提供干净的工作表。
| 归档时间: |
|
| 查看次数: |
8866 次 |
| 最近记录: |