公认的答案是在每个@SpringBootTest测试夹具类中定义一个嵌套类,用@TestConfiguration对其进行注释,并在其中为每个需要解析的bean定义一个工厂方法。嵌套类的影响范围为测试夹具,影响到夹具中的所有测试,但不影响在其他夹具中定义的测试。
这提供了对在每个测试夹具中运行测试时注入到组件中的依赖项的细粒度控制。
这种方法的问题在于它需要在每个测试夹具类中添加一个嵌套的解析器类。这是不可伸缩的。考虑一个有10个测试装置的项目。其中9个使用相同的注入依赖项,而第10个只需要对一个特定接口执行不同的实现。
在这种情况下,我需要将测试配置类复制到9个测试夹具类中,并且只对第10个测试使用第二个配置类。
我需要一种更可伸缩的方法来做这件事。例如,在上述情况下,我希望能够定义两个配置类,一个用于测试夹具使用的两个配置。然后,我希望能够为每个测试夹具指定应该使用的两个配置类中的哪个。我试过:
@Import注释将一个文本夹具的嵌套配置类导入另一个测试夹具,但是当这样做时,配置类在后者中被忽略。因此,总之,我正在寻找一种有效的方法,允许我只编写每个配置类一次,然后选择性地将一个类应用于每个SpringBootTest类,而不需要复制它。
发布于 2019-10-27 22:39:25
经过一些实验,我得到了以下解决方案。我也将添加所有的细节,总结我在the previous question中学到的东西。
背景
我们有两个接口:和IServer
要求
中使用@SpringBootTest注释)
- InterfaceTests defines tests that should use a MockServer and a MockClient
- ClientTests defines tests that should use a MockServer and RealClient to test the RealClient.
- ServerTests defines tests that should use a MockClient and a RealServer to test the RealServer.
- IntegrationTests defines tests that should use a RealServer and a RealClient
从上面可以清楚地看到,模拟/真实客户机/服务器有四个组合,每个组合都需要在代码的某些区域。
解决方案
该解决方案使用@Configuration和@TestConfiguration注解来实现这些需求,而不需要重复代码。
@Component
@Configuration
public class RealInjector {
@Bean
public IServer createServer(){
return new RealServer();
}
@Bean
public IClient createClient(){
return new RealClient();
}
}测试/java中的
@TestConfiguration
public class AllMockInjector {
@Bean
public IServer createServer(){
return new MockServer();
}
@Bean
public IClient createClient(){
return new MockClient();
}
}
@TestConfiguration
public class MockServerInjector{
@Bean
public IServer createServer(){
return new MockServer();
}
@Bean
public IClient createClient(){
return new RealClient();
}
}
@TestConfiguration
public class MockClientInjector{
@Bean
public IServer createServer(){
return new RealServer();
}
@Bean
public IClient createClient(){
return new MockClient();
}
}@RunWith(SpringRunner.class)
@SpringBootTest(classes = {AllMockInjector.class})
public class InterfaceTests { ... }@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MockServerInjector.class})
public class ClientTests { ... }@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MockClientInjector.class})
public class ServerTests { ... }@RunWith(SpringRunner.class)
@SpringBootTest(classes = {RealInjector.class})
public class IntegrationTests { ... }最后
为了让测试配置类覆盖main/java中的RealInjector配置类,我们需要设置属性:
spring.main.allow-bean-definition-overriding=true 这样做的一种方法是对上述每个测试夹具进行注释,如下所示:
@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
class TestFixture { ... }但这是相当冗长的,特别是当你有许多测试装置。相反,您可以在测试/资源下的application.properties文件中添加以下内容:
spring.main.allow-bean-definition-overriding=true您还可能需要将其添加到application.properties中的main/resources中。
摘要
该解决方案为您提供了对注入到代码中用于生产和测试的实现的细粒度控制。该解决方案不需要代码复制或外部配置文件(除了test/resources/application.properties中的一个属性外)。
https://stackoverflow.com/questions/58583454
复制相似问题