2016-03-30 16 views
5

Tôi đã chạy vào các sự cố @ComponentScan với @Configuration các lớp để kiểm tra - cụ thể là, @ComponentScan được kéo trong không mong muốn @Configuration trong khi kiểm tra tích hợp.Loại trừ cấu hình trong các lớp thử nghiệm từ @ComponentScan

Ví dụ, nói rằng bạn đã có một số cấu hình toàn cầu trong src/main/java mà kéo trong thành phần trong com.example.service, com.example.config.GlobalConfiguration:

package com.example.config; 
... 
@Configuration 
@ComponentScan(basePackageClasses = ServiceA.class) 
public class GlobalConfiguration { 
    ... 
} 

Nó nhằm kéo trong hai dịch vụ, com.example.services.ServiceAcom.example.services.ServiceB, chú thích với @Component@Profile("!test") (bỏ qua cho ngắn gọn).

Sau đó, trong src/kiểm tra/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...); 
     } 
    } 
} 

Và cũng com.example.ServiceBIntegrationTest, mà cần phải kéo trong GlobalConfiguration.class để có một thử nghiệm hội nhập, nhưng vẫn tránh được kéo trong việc triển khai nguy hiểm với @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...); 
     } 
    } 
} 

Mục đích rõ ràng của ServiceBIntegrationTest là để kéo trong cấu hình src/main/java ứng dụng hoàn toàn qua GlobalConfiguration, loại trừ nguy hiểm thành phần thông qua @ActiveProfiles("test") và thay thế các thành phần bị loại trừ bằng cách triển khai của riêng nó. Tuy nhiên, trong các thử nghiệm, không gian tên của src/main/javasrc/test/java được kết hợp, do đó, GlobalConfiguration 's @ComponentScan tìm thấy nhiều hơn trong đường dẫn lớp so với thông thường, cụ thể là hạt ServiceA được xác định trong ServiceA.ServiceATestConfiguration. Điều đó có thể dễ dàng dẫn đến xung đột và kết quả không mong muốn.

Bây giờ, bạn có thể làm điều gì đó trên GlobalConfiguration như @ComponentScan(..., excludeFilters= @ComponentScan.Filter(type = FilterType.REGEX, pattern = "\\.*(T|t)est\\.*")), nhưng điều đó có vấn đề của riêng nó. Dựa vào quy ước đặt tên là khá giòn; vẫn còn, ngay cả khi bạn đã sao lưu chú thích @TestConfiguration và sử dụng FilterType.ANNOTATION, bạn có thể thực hiện một cách hiệu quả sốcủa mình về số src/test/java của mình, không được, IMO (xem lưu ý bên dưới).

Vì nó là viết tắt, tôi đã giải quyết được sự cố của mình bằng cách sử dụng hồ sơ bổ sung. Trên ServiceA, tôi thêm tên tiểu sử duy nhất - để chú thích tiểu sử của nó trở thành một cái gì đó như @ActiveProfiles("test,serviceatest"). Sau đó, trên ServiceATest.ServiceATestConfiguration tôi thêm chú thích @Profile("serviceatest"). Này có hiệu quả hạn chế phạm vi ServiceATestConfiguration với tương đối ít trên cao, nhưng nó có vẻ như một trong hai:

a) Tôi đang sử dụng @ComponentScan không đúng cách, hoặc

b) Có phải là một mô hình sạch hơn nhiều để xử lý vấn đề này

Đó là gì?


lưu ý: yes, ứng dụng sẽ kiểm tra nhận thức bởi vì nó sử dụng @Profile("!test"), nhưng tôi muốn tranh luận làm cho việc áp dụng một chút thử nghiệm-aware để bảo vệ chống lại việc sử dụng tài nguyên không đúng cách và làm cho nó kiểm tra nhận thức để đảm bảo tính chính xác của các bài kiểm tra là những điều rất khác nhau.

Trả lời

1

Tôi thấy bạn đang cố gắng giả đậu mùa xuân trong quá trình thử nghiệm tích hợp.Nếu bạn kết hợp chú thích @Profile@ActiveProfiles với chú thích @Primary, hầu hết các cơn đau đầu của bạn sẽ biến mất và bạn không cần đánh dấu các hạt sản xuất với @Profile("!test").

Tôi đã viết blog post on the topic với Github examples.

Phản ứng về nhận xét:

Theo cấu trúc gói. Quét thành phần quét tất cả các gói trong gói và gói con hiện tại. NẾU bạn không muốn quét đậu, chỉ cần sửa đổi cấu trúc gói của bạn theo cách mà đậu sẽ không được dưới ô quét thành phần của bạn.

Mùa xuân không phân biệt các gói từ src/test/java hoặc src/main/java. Cố gắng loại trừ đậu sản xuất với @Profile("!test") là mùi thiết kế. Bạn nên tránh nó. Tôi sẽ đề nghị cho một cơ hội để tiếp cận từ blog được đề cập.

Lưu ý rằng khi bạn ghi đè lên bean với chú thích @Primary, bạn có thể cần phải sử dụng chú thích @DirtiesContext để có bảng sạch cho các thử nghiệm khác.

+1

Vâng, có một số lợi thế cho mẫu đó, nhưng đó không phải là câu hỏi của tôi. Tôi đang hỏi cách giới hạn tốt nhất phạm vi cấu hình trong gói được quét thành phần. – jwilner

+1

Thay đổi bao bì sẽ xung đột với phạm vi gói địa phương, điều này rõ ràng là quan trọng đối với thử nghiệm. Điều này là không đạt yêu cầu. – jwilner

Các vấn đề liên quan