带有 @Configuration 的内部静态类由 spring 扫描仪为所有测试拾取。怎么了?

Fir*_*ire 5 junit spring spring-boot

Spring@Configuration从 Test2 中拾取用于 Test1 的内部。我需要IService在 Test2 中模拟,但ServiceImpl在 Test1 中需要真实。我也想对TestConfiguration我所有的测试都有共同点。但我总是在两个测试中嘲笑 IService。怎么了?

如何禁用为兄弟测试拾取的内部配置?

这是我的代码:

ServiceImpl.java:

@Service
public class SeriviveImpl implements IService {
}
Run Code Online (Sandbox Code Playgroud)

测试配置.java:

@Configuration
@ComponentScan
public class TestConfiguration {
   // empty
}
Run Code Online (Sandbox Code Playgroud)

测试1.java:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestConfiguration.class})
public class Test1 {
    @Autowired
    private IService service;
}
Run Code Online (Sandbox Code Playgroud)

测试2.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Test2.CustomConfiguration.class, TestConfiguration.class})
public class Test2 {
    @Autowired
    private IService service;

    @Configuration
    static class CustomConfiguration {
        @Bean
        IService service() {
            return mock(IService.class);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Plo*_*log 5

您可以从 TestConfiguration @ComponentScan 中过滤内部类:

@Configuration
@ComponentScan(excludeFilters = {
     @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
                           value = Test2.CustomConfiguration.class)
})
public class TestConfiguration {
   // empty
}
Run Code Online (Sandbox Code Playgroud)

这将防止它在 Test1 中被拾取。

编辑或者如果您有很多内部配置,您可以创建自己的注释并从 @ComponentScan 过滤所有这些带注释的类:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
public @interface InnerConfiguration {
}
Run Code Online (Sandbox Code Playgroud)

然后在您的内部类上使用此注释而不是@Configuration:

@InnerConfiguration
    static class CustomConfiguration {
        @Bean
        IService service() {
            return mock(IService.class);
        }
    }
Run Code Online (Sandbox Code Playgroud)

并从组件扫描中过滤掉这些内容,如下所示:

@Configuration
@ComponentScan(excludeFilters = {
     @ComponentScan.Filter(type = FilterType.ANNOTATION,
                           value = InnerConfiguration.class)
})
public class TestConfiguration {
   // empty
}
Run Code Online (Sandbox Code Playgroud)