1 回答

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超9個(gè)贊
經(jīng)過一些實(shí)驗(yàn),我得到了以下解決方案。
背景
我們有兩個(gè)接口:IClient 和 IServer
IClient 有兩種實(shí)現(xiàn):RealClient 和 MockClient。
IServer 有兩種實(shí)現(xiàn):RealServer 和 MockServer。
要求
生產(chǎn)代碼(在 main/java 中)應(yīng)該使用兩者的 Real 實(shí)現(xiàn)。
測(cè)試夾具(在test/java中用@SpringBootTest注釋)
InterfaceTests 定義了應(yīng)該使用 MockServer 和 MockClient 的測(cè)試
ClientTests 定義了應(yīng)該使用 MockServer 和 RealClient 來測(cè)試 RealClient 的測(cè)試。
ServerTests 定義了應(yīng)該使用 MockClient 和 RealServer 來測(cè)試 RealServer 的測(cè)試。
IntegrationTests 定義應(yīng)使用 RealServer 和 RealClient 的測(cè)試
從上面可以清楚地看出,模擬/真實(shí)客戶端/服務(wù)器有四種組合,并且每種組合在代碼的某些區(qū)域都需要。
解決方案
該解決方案利用 @Configuration 和 @TestConfiguration 注釋來實(shí)現(xiàn)這些要求,而無需重復(fù)代碼。
不要使用 @Component 注釋接口及其實(shí)現(xiàn)
在main/java下實(shí)現(xiàn)一個(gè)配置類如下:
@Configuration
public class RealInjector {
? ? @Bean
? ? public IServer createServer(){
? ? ? ? return new RealServer();
? ? }
? ? @Bean
? ? public IClient createClient(){
? ? ? ? return new RealClient();
? ? }
}
在test/java下實(shí)現(xiàn)這三個(gè)測(cè)試配置類
@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();
? ? }
}
將 InterfaceTests 測(cè)試裝置注釋如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {AllMockInjector.class})
public class InterfaceTests { ... }
將 ClientTests 測(cè)試裝置注釋如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MockServerInjector.class})
public class ClientTests { ... }
將 ServerTests 測(cè)試裝置注釋如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MockClientInjector.class})
public class ServerTests { ... }
按如下方式注釋 IntegrationTests 測(cè)試裝置:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {RealInjector.class})
public class IntegrationTests { ... }
最后
為了讓測(cè)試配置類覆蓋 main/java 中的 RealInjector 配置類,我們需要設(shè)置屬性:
spring.main.allow-bean-definition-overriding=true?
一種方法是對(duì)上述每個(gè)測(cè)試裝置進(jìn)行注釋,如下所示:
@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
class TestFixture { ... }
但這非常冗長,特別是如果您有很多測(cè)試裝置。相反,您可以在 test/resources 下的 application.properties 文件中添加以下內(nèi)容:
spring.main.allow-bean-definition-overriding=true
您可能還需要將其添加到 main/resources 下的 application.properties 中。
概括
該解決方案使您能夠?qū)ψ⑷氲缴a(chǎn)和測(cè)試代碼中的實(shí)現(xiàn)進(jìn)行細(xì)粒度控制。該解決方案不需要重復(fù)代碼或外部配置文件(除了 test/resources/application.properties 中的一個(gè)屬性)。
添加回答
舉報(bào)