[英]How can I use composition of the classes if they have common fields in java?
[英]How can I efficiently use nested configuration classes to inject dependencies when I have many SpringBootTest classes
公認的答案是在每個@SpringBootTest
測試夾具 class 中定義一個嵌套的 class,用@TestConfiguration
對其進行注釋,並在其中為每個需要解析的 bean 定義一個工廠方法。 嵌套類的影響范圍僅限於測試夾具,影響夾具中的所有測試,但不影響其他夾具中定義的測試。
當在每個測試夾具中運行測試時,這提供了對注入到組件中的依賴項的細粒度控制。
這種方法的問題在於,它需要在每個測試夾具 class 中添加嵌套解析器 class。 這是不可擴展的。 考慮一個有 10 個測試裝置的項目。 其中 9 個使用相同的注入依賴項,只有第 10 個需要針對一個特定接口的不同實現。
在這種情況下,我需要將測試配置 class 復制到 9 個測試夾具類中,並僅在第 10 次測試中使用第二個配置 class。
我需要一種更具可擴展性的方式來做到這一點。 例如,在上面的例子中,我希望能夠定義兩個配置類,一個用於測試夾具使用的兩個配置中的每一個。 然后我希望能夠為每個測試夾具指定應該使用兩個配置類中的哪一個。 我努力了:
@Import
注釋將一個文本夾具的嵌套配置 class 導入另一個測試夾具,但是這樣做時,配置 class 在后者中被忽略。因此,總而言之,我正在尋找一種有效的方法,它允許我只編寫每個配置 class 一次,然后選擇性地將一個配置應用於每個 SpringBootTest class 而無需復制它。
經過一些實驗,我達到了以下解決方案。 我將添加所有細節來總結我在上一個問題中學到的東西。
測試夾具(在 test/java 中用 @SpringBootTest 注釋)
從上面可以清楚地看出,模擬/真實客戶端/服務器有四種組合,並且在代碼的某些區域需要每種組合。
此解決方案利用 @Configuration 和 @TestConfiguration 注釋來實現這些要求,而無需重復代碼。
@Configuration
public class RealInjector {
@Bean
public IServer createServer(){
return new RealServer();
}
@Bean
public IClient createClient(){
return new RealClient();
}
}
@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 配置 class,我們需要設置屬性:
spring.main.allow-bean-definition-overriding=true
一種方法是對上述每個測試夾具進行如下注釋:
@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
class TestFixture { ... }
但這非常冗長,特別是如果您有很多測試裝置。 相反,您可以在 test/resources 下的 application.properties 文件中添加以下內容:
spring.main.allow-bean-definition-overriding=true
您可能還需要在 main/resources 下的 application.properties 中添加它。
此解決方案使您可以對注入到您的代碼中以用於生產和測試的實現進行細粒度控制。 該解決方案不需要代碼重復或外部配置文件(除了 test/resources/application.properties 中的一個屬性)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.