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.ServiceA
và com.example.services.ServiceB
, chú thích với @Component
và @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/java
và src/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.
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
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