2017-02-15 114 views
1

我類..排除Spring組件特定類掃描而寫Spring集成測試

在於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); 
} 
} 

現在的問題是我想排除類 get component scanning.my這個類包含對apache Kafka的依賴關係。 如果這個類在容器啓動時加載,它開始尋找kafka運行實例。 因此,在運行Intregation測試時,我不會啓動我的Kafka服務器,所以我想運行 使kafka關機的內部測試。

此我可以通過addding這條線將其從被獲取部件掃描不含OrderReceiveEventConfiguration類代碼StoreOrderFulfillmentApplication類的添加一行代碼在StoreOrderFulfillmentApplication類

@ComponentScan(basePackages = "com.tesco.store.order.fulfillment.processor", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = OrderReceiveEventConfiguration.class)) 

實現。

現在的問題是我不會在主代碼中添加任何測試配置更改。 所以我很努力去做src/intregation-test/java源文件夾中的排除,這是他們在容器啓動代碼期間排除這個特定類的一些方法。

但它不應該影響我的主類的代碼意味着內部的src/main/java的

任何幫助表示讚賞代碼..

+0

你想測試應用程序的行爲,當Kafka關閉/不運行或者你只是想在測試時忽略卡夫卡部分? –

+0

是@ Bond-JavaBond,我想在測試時忽略kafka部分... 實際上我的要求說,在執行測試套件時,應該像數據庫或消息隊列一樣嘲笑外部依賴關係... 在我的測試框數據庫和消息隊列服務器中不這樣做的原因,所以我們必須準備我們的測試套件,因爲它不應該檢查連接性。 –

回答

0

您可以使用@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(); 
} 

豆條件

@ConditionalOnBean@ConditionalOnMissingBean註解允許基於特定豆的存在或不存在要被包括的bean。您可以使用value屬性來按類型指定bean,或者使用名稱來指定bean的名稱。搜索屬性允許您限制搜索bean時應考慮的ApplicationContext層次結構。

查看上面的例子,當我們檢查是否沒有定義的bean。

物業條件

@ConditionalOnProperty註釋允許基於Spring的環境屬性,包括配置。使用前綴和名稱屬性來指定應該檢查的屬性。默認情況下,任何存在且不等於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註釋允許基於SpeI位表達式的結果被包括配置。

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

'@Configuration @EnableBinding(Source.class) 公共類OrderReceiveEventConfiguration { \t \t公共OrderReceiveEventConfiguration(){ \t} \t \t @Value( 「$ {} spring.outputChannel.timeout.ms」) \t private long timeoutMs; \t public long getTimeoutMs(){ \t \t return timeoutMs; \t} \t公共無效setTimeoutMs(長timeoutMs){ \t \t this.timeoutMs = timeoutMs; \t} \t }' 這是我的班,你能告訴我將如何使用@Conditional這裏* –

+0

它應該是這樣的'@Configuration @EnableBinding(Source.class)@Conditional(PropertyCondition.class)公共類OrderReceiveEventConfiguration {...}' –

+0

謝謝....這個解決方案對我來說是.... –

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

不工作@mirmdasif .. –

+0

@mirmdasif,不包括我在測試的情況下不工作(但是@ @ ComponentScan'註釋本身正在工作 - 例如basePackages使不同) – atsu85

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

添加以下內容ing配置註釋給你測試類

@SpringApplicationConfiguration(classes = TestStoreOrderFulfillmentApplication .class)