亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當我有很多 SpringBootTest 類時,如何有效地使用嵌套配置類來注入依賴項

當我有很多 SpringBootTest 類時,如何有效地使用嵌套配置類來注入依賴項

BIG陽 2024-01-05 15:02:55
這個問題是Can I use code to control the dependency resolution Decisions made by ApplicationContext in Spring Boot? 的續集。@SpringBootTest可接受的答案是在每個測試夾具類中定義一個嵌套類,對其進行注釋@TestConfiguration并在其中為需要解析的每個 bean 定義一個工廠方法。嵌套類的影響范圍僅限于測試裝置,影響裝置中的所有測試,但不影響其他裝置中定義的測試。當在每個測試裝置中運行測試時,這提供了對注入組件的依賴項的細粒度控制。這種方法的問題是它需要在每個測試夾具類中添加一個嵌套的解析器類。這是不可擴展的??紤]一個具有 10 個測試裝置的項目。其中 9 個使用相同的注入依賴項,只有第 10 個僅需要一個特定接口的不同實現。在這種情況下,我需要將測試配置類復制到 9 個測試夾具類中,并僅在第 10 個測試中使用第二個配置類。我需要一種更具可擴展性的方法來做到這一點。例如,在上面的情況下,我希望能夠定義兩個配置類,一個用于測試裝置使用的兩種配置中的每一種。然后我希望能夠為每個測試裝置指定應使用兩個配置類中的哪一個。我努力了:我嘗試使用注釋將一個文本夾具的嵌套配置類導入到另一個測試夾具中@Import,但這樣做時,后者中的配置類被忽略。我還嘗試將嵌套配置類移動到上層,以便它可以用于未明確將不同配置類定義為嵌套類的所有測試裝置,但在這種情況下,所有測試裝置都會忽略配置類??傊?,我正在尋找一種有效的方法,該方法允許我只編寫每個配置類一次,然后有選擇地將一個配置類應用于每個 SpringBootTest 類,而無需復制它。
查看完整描述

1 回答

?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

經過一些實驗,我得到了以下解決方案。

背景

  1. 我們有兩個接口:IClient 和 IServer

  2. IClient 有兩種實現:RealClient 和 MockClient。

  3. IServer 有兩種實現:RealServer 和 MockServer。

要求

  1. 生產代碼(在 main/java 中)應該使用兩者的 Real 實現。

  2. 測試夾具(在test/java中用@SpringBootTest注釋)

  • InterfaceTests 定義了應該使用 MockServer 和 MockClient 的測試

  • ClientTests 定義了應該使用 MockServer 和 RealClient 來測試 RealClient 的測試。

  • ServerTests 定義了應該使用 MockClient 和 RealServer 來測試 RealServer 的測試。

  • IntegrationTests 定義應使用 RealServer 和 RealClient 的測試

從上面可以清楚地看出,模擬/真實客戶端/服務器有四種組合,并且每種組合在代碼的某些區域都需要。

解決方案

該解決方案利用 @Configuration 和 @TestConfiguration 注釋來實現這些要求,而無需重復代碼。

  1. 不要使用 @Component 注釋接口及其實現

  2. 在main/java下實現一個配置類如下:


@Configuration

public class RealInjector {

? ? @Bean

? ? public IServer createServer(){

? ? ? ? return new RealServer();

? ? }


? ? @Bean

? ? public IClient createClient(){

? ? ? ? return new RealClient();

? ? }

}


在test/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();

? ? }

}


將 InterfaceTests 測試裝置注釋如下:

@RunWith(SpringRunner.class)

@SpringBootTest(classes = {AllMockInjector.class})

public class InterfaceTests { ... }

將 ClientTests 測試裝置注釋如下:

@RunWith(SpringRunner.class)

@SpringBootTest(classes = {MockServerInjector.class})

public class ClientTests { ... }

將 ServerTests 測試裝置注釋如下:

@RunWith(SpringRunner.class)

@SpringBootTest(classes = {MockClientInjector.class})

public class ServerTests { ... }

按如下方式注釋 IntegrationTests 測試裝置:

@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 { ... }

但這非常冗長,特別是如果您有很多測試裝置。相反,您可以在 test/resources 下的 application.properties 文件中添加以下內容:


spring.main.allow-bean-definition-overriding=true

您可能還需要將其添加到 main/resources 下的 application.properties 中。


概括

該解決方案使您能夠對注入到生產和測試代碼中的實現進行細粒度控制。該解決方案不需要重復代碼或外部配置文件(除了 test/resources/application.properties 中的一個屬性)。


查看完整回答
反對 回復 2024-01-05
  • 1 回答
  • 0 關注
  • 141 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號