编写Spring Integration Test时,从Spring Component扫描中排除特定类

时间:2017-02-15 09:22:16

标签: java spring spring-mvc spring-boot spring-test

我的班级是......

位于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);
}
}

现在问题是我想要排除一个类 从获取组件scan.my此类包含apache Kafka的依赖项。 如果在启动容器时加载此类,则会开始查找kafka运行实例。 所以在运行Intregation测试时我不会启动我的Kafka服务器,所以我想运行 隔离测试使kafka关闭。

我可以通过在StoreOrderFulfillmentApplication类

中添加一行代码来实现
@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class))

通过添加这行代码StoreOrderFulfillmentApplication类,它排除了OrderReceiveEventConfiguration类被扫描的组件。

现在问题是我不想在主代码中添加任何测试配置更改。 所以我很难从 src / intregation-test / java 源文件夹中做同样的排除,他们可以在容器启动代码中排除这个特定的类。

但它不应该影响我的主类代码意味着代码 src / main / java

任何帮助都是赞赏的。

3 个答案:

答案 0 :(得分:1)

您可以使用@Conditional,如下所示。

  • application.properties中引入属性kafka.enabled
  • 使用OrderReceiveEventConfiguration
  • 注释@Conditional(PropertyCondition.class)
  • 取决于kafka.enabled值即。 true用于正常运行)或false用于测试OrderReceiveEventConfiguration将分别被选中或忽略,而不会更改码。

如果需要更多信息,请在评论中告知。

除主@conditional注释外,还有一组类似的注释用于不同的情况。

班级条件

@ConditionalOnClass@ConditionalOnMissingClass注释允许根据特定类的存在与否来包含配置。

E.g。当OObjectDatabaseTx.class被添加到依赖项并且没有OrientWebConfigurer bean时,我们创建了配置器。

@Bean
@ConditionalOnWebApplication
@ConditionalOnClass(OObjectDatabaseTx.class)
@ConditionalOnMissingBean(OrientWebConfigurer.class)
public OrientWebConfigurer orientWebConfigurer() {
    return new OrientWebConfigurer();
}

Bean条件

@ConditionalOnBean@ConditionalOnMissingBean注释允许根据特定bean的存在与否来包含bean。您可以使用value属性按类型指定bean,或使用name来按名称指定bean。 search属性允许您限制搜索bean时应考虑的ApplicationContext层次结构。

当我们检查是否没有定义的bean时,请参阅上面的示例。

物业条件

@ConditionalOnProperty注释允许基于Spring Environment属性包含配置。使用prefix和name属性指定应检查的属性。默认情况下,将匹配存在且不等于false的任何属性。您还可以使用havingValuematchIfMissing属性创建更高级的检查。

@ConditionalOnProperty(value='somebean.enabled', matchIfMissing = true, havingValue="yes")
@Bean 
public SomeBean someBean(){
}

资源条件

@ConditionalOnResource注释仅允许在存在特定资源时包含配置。

@ConditionalOnResource(resources = "classpath:init-db.sql") 

Web应用程序条件

@ConditionalOnWebApplication@ConditionalOnNotWebApplication注释允许包含配置,具体取决于应用程序是否为“Web应用程序”。

@Configuration
@ConditionalOnWebApplication
public class MyWebMvcAutoConfiguration {...}

SpEL表达条件

@ConditionalOnExpression注释允许根据SpEL表达式的结果包含配置。

@ConditionalOnExpression("${rest.security.enabled}==false")

答案 1 :(得分:0)

您应该能够在测试包中创建单独的配置类

@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);
}
}

然后在你的测试课

@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());
}

答案 2 :(得分:0)

创建测试应用程序类

@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);
}
}

将以下配置注释添加到测试类

@SpringApplicationConfiguration(classes = TestStoreOrderFulfillmentApplication .class)