在编写 Spring 集成测试时从 Spring 组件扫描中排除特定 class
Exclude a particular class from Spring Component scan while writing Spring Integration Test
我的class是..
在于src/intregation-test/java
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = StoreOrderFulfillmentApplication.class)
@ActiveProfiles("Test")
public class OrderCreationIntregationTest {
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private OrderRepository orderRepository;
@MockBean
private OrderLineItemRepository orderLineItemRepository;
@MockBean
private InternalEventPublisher internalEventPublisher;
@SuppressWarnings("unchecked")
@Before
public void setup() {
Mockito.when(orderRepository.findByOfsReferenceId("OFS:GMO:Z100002062-99")).thenReturn(null);
OrderEntity savedOrder = new OrderEntity();
savedOrder.setOrderId(1023);
Mockito.when(orderRepository.save(Mockito.any(OrderEntity.class))).thenReturn(savedOrder);
Iterable<OrderLineItemEntity> orderLineItemList = prepareOrderLineItemEntityIterable();
Mockito.when(orderLineItemRepository.save(Mockito.any(Iterable.class))).thenReturn(orderLineItemList);
}
@Test
public void test() throws ParseException {
FulfillmentOrder fulfillmentOrderRequestVO = new FulfillmentOrder();
fulfillmentOrderRequestVO = buildFulfillmentOrder();
String myMessage = "Order Created";
ResponseEntity<ResponseOrderMessage> responseEntity = restTemplate.postForEntity("/fulfillmentprocessor/orders",
fulfillmentOrderRequestVO, ResponseOrderMessage.class);
ResponseOrderMessage responseOrderMessage = responseEntity.getBody();
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(myMessage, responseOrderMessage.getMessage());
}
在于src/main/java
@SpringBootApplication
public class StoreOrderFulfillmentApplication {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplication.class, args);
}
}
现在的问题是我想排除 class
从获取组件 scanned.my 开始,此 class 包含对 apache Kafka 的依赖项。
如果这个 class 在容器启动时加载,它会开始寻找 kafka 运行ning 实例。
所以在 运行 宁集成测试时我不会启动我的 Kafka 服务器,所以我想 运行
集成测试使 kafka 关闭。
我可以通过在 StoreOrderFulfillmentApplication 中添加一行代码来实现 class
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
通过添加这行代码 StoreOrderFulfillmentApplication class 它从获取组件扫描中排除了 OrderReceiveEventConfiguration class。
现在的问题是我不认为在主代码中添加任何测试配置更改。
所以我正在努力从 src/intregation-test/java 源文件夹中进行同样的排除,这是我可以在容器启动代码期间排除这个特定 class 的某种方式。
但它不应该影响我的主要 class 代码意味着代码在 src/main/java
感谢任何帮助..
您可以使用 @Conditional
,如下所示。
- 在
application.properties
中引入一个属性说kafka.enabled
。
- 用
@Conditional(PropertyCondition.class)
注释OrderReceiveEventConfiguration
- 取决于
kafka.enabled
值即。 true
(正常运行)或false
(测试) OrderReceiveEventConfiguration
将在不更改代码的情况下分别被拾取或忽略。
如果需要更多信息,请在评论中告知。
除了主要的 @conditional
注释外,还有一组类似的注释可用于不同的情况。
Class 条件
@ConditionalOnClass
和 @ConditionalOnMissingClass
注释允许根据特定 类.
的存在或不存在来包含配置
例如当 OObjectDatabaseTx.class
添加到依赖项并且没有 OrientWebConfigurer
bean 时,我们创建配置器。
@Bean
@ConditionalOnWebApplication
@ConditionalOnClass(OObjectDatabaseTx.class)
@ConditionalOnMissingBean(OrientWebConfigurer.class)
public OrientWebConfigurer orientWebConfigurer() {
return new OrientWebConfigurer();
}
豆子情况
@ConditionalOnBean
和 @ConditionalOnMissingBean
注释允许根据特定 bean 的存在或不存在来包含 bean。您可以使用 value 属性按类型指定 bean,或使用 name 按名称指定 bean。 search 属性允许您限制搜索 bean 时应考虑的 ApplicationContext
层次结构。
查看是否没有定义的bean,见上例
属性 条件
@ConditionalOnProperty
注释允许包含基于 Spring 环境 属性 的配置。使用前缀和名称属性指定应检查的 属性。默认情况下,将匹配存在且不等于 false
的任何 属性。您还可以使用 havingValue
和 matchIfMissing
属性创建更高级的检查。
@ConditionalOnProperty(value='somebean.enabled', matchIfMissing = true, havingValue="yes")
@Bean
public SomeBean someBean(){
}
资源条件
@ConditionalOnResource
注释允许仅在存在特定资源时包含配置。
@ConditionalOnResource(resources = "classpath:init-db.sql")
Web申请条件
@ConditionalOnWebApplication
和 @ConditionalOnNotWebApplication
注释允许根据应用程序是否为 'web application'.
添加配置。
@Configuration
@ConditionalOnWebApplication
public class MyWebMvcAutoConfiguration {...}
SpEL 表达条件
@ConditionalOnExpression
注释允许根据 SpEL 表达式的结果包含配置。
@ConditionalOnExpression("${rest.security.enabled}==false")
您应该能够在测试包中创建单独的配置 class
@SpringBootApplication
@ActiveProfiles("Test")
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
public class StoreOrderFulfillmentApplicationTest {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplicationTest.class, args);
}
}
然后在你的测试中class
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = StoreOrderFulfillmentApplicationTest.class)
@ActiveProfiles("Test")
public class OrderCreationIntregationTest {
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private OrderRepository orderRepository;
@MockBean
private OrderLineItemRepository orderLineItemRepository;
@MockBean
private InternalEventPublisher internalEventPublisher;
@SuppressWarnings("unchecked")
@Before
public void setup() {
Mockito.when(orderRepository.findByOfsReferenceId("OFS:GMO:Z100002062-99")).thenReturn(null);
OrderEntity savedOrder = new OrderEntity();
savedOrder.setOrderId(1023);
Mockito.when(orderRepository.save(Mockito.any(OrderEntity.class))).thenReturn(savedOrder);
Iterable<OrderLineItemEntity> orderLineItemList = prepareOrderLineItemEntityIterable();
Mockito.when(orderLineItemRepository.save(Mockito.any(Iterable.class))).thenReturn(orderLineItemList);
}
@Test
public void test() throws ParseException {
FulfillmentOrder fulfillmentOrderRequestVO = new FulfillmentOrder();
fulfillmentOrderRequestVO = buildFulfillmentOrder();
String myMessage = "Order Created";
ResponseEntity<ResponseOrderMessage> responseEntity = restTemplate.postForEntity("/fulfillmentprocessor/orders",
fulfillmentOrderRequestVO, ResponseOrderMessage.class);
ResponseOrderMessage responseOrderMessage = responseEntity.getBody();
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(myMessage, responseOrderMessage.getMessage());
}
创建测试应用程序class
@SpringBootApplication
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
public class TestStoreOrderFulfillmentApplication {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplication.class, args);
}
}
添加以下配置注解给你测试class
@SpringApplicationConfiguration(classes = TestStoreOrderFulfillmentApplication .class)
我的class是..
在于src/intregation-test/java
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = StoreOrderFulfillmentApplication.class)
@ActiveProfiles("Test")
public class OrderCreationIntregationTest {
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private OrderRepository orderRepository;
@MockBean
private OrderLineItemRepository orderLineItemRepository;
@MockBean
private InternalEventPublisher internalEventPublisher;
@SuppressWarnings("unchecked")
@Before
public void setup() {
Mockito.when(orderRepository.findByOfsReferenceId("OFS:GMO:Z100002062-99")).thenReturn(null);
OrderEntity savedOrder = new OrderEntity();
savedOrder.setOrderId(1023);
Mockito.when(orderRepository.save(Mockito.any(OrderEntity.class))).thenReturn(savedOrder);
Iterable<OrderLineItemEntity> orderLineItemList = prepareOrderLineItemEntityIterable();
Mockito.when(orderLineItemRepository.save(Mockito.any(Iterable.class))).thenReturn(orderLineItemList);
}
@Test
public void test() throws ParseException {
FulfillmentOrder fulfillmentOrderRequestVO = new FulfillmentOrder();
fulfillmentOrderRequestVO = buildFulfillmentOrder();
String myMessage = "Order Created";
ResponseEntity<ResponseOrderMessage> responseEntity = restTemplate.postForEntity("/fulfillmentprocessor/orders",
fulfillmentOrderRequestVO, ResponseOrderMessage.class);
ResponseOrderMessage responseOrderMessage = responseEntity.getBody();
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(myMessage, responseOrderMessage.getMessage());
}
在于src/main/java
@SpringBootApplication
public class StoreOrderFulfillmentApplication {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplication.class, args);
}
}
现在的问题是我想排除 class 从获取组件 scanned.my 开始,此 class 包含对 apache Kafka 的依赖项。 如果这个 class 在容器启动时加载,它会开始寻找 kafka 运行ning 实例。 所以在 运行 宁集成测试时我不会启动我的 Kafka 服务器,所以我想 运行 集成测试使 kafka 关闭。
我可以通过在 StoreOrderFulfillmentApplication 中添加一行代码来实现 class
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
通过添加这行代码 StoreOrderFulfillmentApplication class 它从获取组件扫描中排除了 OrderReceiveEventConfiguration class。
现在的问题是我不认为在主代码中添加任何测试配置更改。 所以我正在努力从 src/intregation-test/java 源文件夹中进行同样的排除,这是我可以在容器启动代码期间排除这个特定 class 的某种方式。
但它不应该影响我的主要 class 代码意味着代码在 src/main/java
感谢任何帮助..
您可以使用 @Conditional
,如下所示。
- 在
application.properties
中引入一个属性说kafka.enabled
。 - 用
@Conditional(PropertyCondition.class)
注释OrderReceiveEventConfiguration
- 取决于
kafka.enabled
值即。true
(正常运行)或false
(测试)OrderReceiveEventConfiguration
将在不更改代码的情况下分别被拾取或忽略。
如果需要更多信息,请在评论中告知。
除了主要的 @conditional
注释外,还有一组类似的注释可用于不同的情况。
Class 条件
@ConditionalOnClass
和 @ConditionalOnMissingClass
注释允许根据特定 类.
例如当 OObjectDatabaseTx.class
添加到依赖项并且没有 OrientWebConfigurer
bean 时,我们创建配置器。
@Bean
@ConditionalOnWebApplication
@ConditionalOnClass(OObjectDatabaseTx.class)
@ConditionalOnMissingBean(OrientWebConfigurer.class)
public OrientWebConfigurer orientWebConfigurer() {
return new OrientWebConfigurer();
}
豆子情况
@ConditionalOnBean
和 @ConditionalOnMissingBean
注释允许根据特定 bean 的存在或不存在来包含 bean。您可以使用 value 属性按类型指定 bean,或使用 name 按名称指定 bean。 search 属性允许您限制搜索 bean 时应考虑的 ApplicationContext
层次结构。
查看是否没有定义的bean,见上例
属性 条件
@ConditionalOnProperty
注释允许包含基于 Spring 环境 属性 的配置。使用前缀和名称属性指定应检查的 属性。默认情况下,将匹配存在且不等于 false
的任何 属性。您还可以使用 havingValue
和 matchIfMissing
属性创建更高级的检查。
@ConditionalOnProperty(value='somebean.enabled', matchIfMissing = true, havingValue="yes")
@Bean
public SomeBean someBean(){
}
资源条件
@ConditionalOnResource
注释允许仅在存在特定资源时包含配置。
@ConditionalOnResource(resources = "classpath:init-db.sql")
Web申请条件
@ConditionalOnWebApplication
和 @ConditionalOnNotWebApplication
注释允许根据应用程序是否为 'web application'.
@Configuration
@ConditionalOnWebApplication
public class MyWebMvcAutoConfiguration {...}
SpEL 表达条件
@ConditionalOnExpression
注释允许根据 SpEL 表达式的结果包含配置。
@ConditionalOnExpression("${rest.security.enabled}==false")
您应该能够在测试包中创建单独的配置 class
@SpringBootApplication
@ActiveProfiles("Test")
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
public class StoreOrderFulfillmentApplicationTest {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplicationTest.class, args);
}
}
然后在你的测试中class
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = StoreOrderFulfillmentApplicationTest.class)
@ActiveProfiles("Test")
public class OrderCreationIntregationTest {
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private OrderRepository orderRepository;
@MockBean
private OrderLineItemRepository orderLineItemRepository;
@MockBean
private InternalEventPublisher internalEventPublisher;
@SuppressWarnings("unchecked")
@Before
public void setup() {
Mockito.when(orderRepository.findByOfsReferenceId("OFS:GMO:Z100002062-99")).thenReturn(null);
OrderEntity savedOrder = new OrderEntity();
savedOrder.setOrderId(1023);
Mockito.when(orderRepository.save(Mockito.any(OrderEntity.class))).thenReturn(savedOrder);
Iterable<OrderLineItemEntity> orderLineItemList = prepareOrderLineItemEntityIterable();
Mockito.when(orderLineItemRepository.save(Mockito.any(Iterable.class))).thenReturn(orderLineItemList);
}
@Test
public void test() throws ParseException {
FulfillmentOrder fulfillmentOrderRequestVO = new FulfillmentOrder();
fulfillmentOrderRequestVO = buildFulfillmentOrder();
String myMessage = "Order Created";
ResponseEntity<ResponseOrderMessage> responseEntity = restTemplate.postForEntity("/fulfillmentprocessor/orders",
fulfillmentOrderRequestVO, ResponseOrderMessage.class);
ResponseOrderMessage responseOrderMessage = responseEntity.getBody();
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(myMessage, responseOrderMessage.getMessage());
}
创建测试应用程序class
@SpringBootApplication
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))
public class TestStoreOrderFulfillmentApplication {
public static void main(String[] args) {
SpringApplication.run(StoreOrderFulfillmentApplication.class, args);
}
}
添加以下配置注解给你测试class
@SpringApplicationConfiguration(classes = TestStoreOrderFulfillmentApplication .class)