Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

下一篇[未完待續]

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>英文原文:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-auto-configuration.html/<code>
<code>GitHub:https://github.com/jijicai/Spring/tree/master/spring-boot/<code>

49.4、測試你的自動配置

自動配置可能受到許多因素的影響:用戶配置(@Bean 定義和 Environment 自定義)、條件評估(特定庫的存在)和其他因素。具體來說,每個測試都應該創建一個定義良好的 ApplicationContext,它表示這些定製的組合。ApplicationContextRunner 提供了一個實現這一點的好方法。

ApplicationContextRunner 通常定義為測試類的一個字段,用於收集基本的公共配置。以下示例確保始終調用 UserServiceAutoConfiguration:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));/<code>

提示:如果必須定義多個自動配置,則無需對其聲明進行排序,因為它們的調用順序與運行應用程序時完全相同。

每個測試都可以使用運行器來表示特定的用例。例如,下面的示例調用用戶配置(UserConfiguration)並檢查自動配置是否正確後退。調用 run 提供了一個可與 Assert4J 一起使用的回調上下文。

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>@Test
public void defaultServiceBacksOff() {
this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(UserService.class);
assertThat(context.getBean(UserService.class))
.isSameAs(context.getBean(UserConfiguration.class).myUserService());
});
}

@Configuration
static class UserConfiguration {

@Bean
public UserService myUserService() {
return new UserService("mine");
}

}/<code>

也可以輕鬆地自定義 Environment,如下面示例所示:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>@Test
public void serviceNameCanBeConfigured() {
this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
assertThat(context).hasSingleBean(UserService.class);
assertThat(context.getBean(UserService.class).getName()).isEqualTo("test123");
});
}/<code>

該運行器還可用於顯示 ConditionEvaluationReport。該報告可以在 INFO 或 DEBUG 級別打印。下面的示例演示如何使用 ConditionEvaluationReportLoggingListener 在自動配置測試中打印報表。

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>@Test
public void autoConfigTest {
ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(

LogLevel.INFO);
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withInitializer(initializer).run((context) -> {
// Do something...
});
}/<code>

49.4.1、模擬 Web 上下文

如果需要測試僅在 Servlet 或 反應式 web 應用程序上下文中運行的自動配置,請分別使用 WebApplicationContextRunner 或 ReactiveWebApplicationContextRunner。

49.4.2、覆蓋 Classpath

也可以測試當特定類和/或包在運行時不存在時會發生什麼。Spring Boot 附帶一個 FilteredClassLoader,可以很容易地被運行器使用。在以下示例中,我們斷言,如果不存在 UserService,則會正確禁用自動配置:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>@Test
public void serviceIsIgnoredIfLibraryIsNotPresent() {
this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class))
.run((context) -> assertThat(context).doesNotHaveBean("userService"));
}/<code>

49.5、創建自己的 Starter

庫的完整 Spring Boot starter 可能包含以下組件:

(1)包含自動配置代碼的 autoconfigure 模塊。

(2)提供對 autoconfigure 模塊、庫和任何其他通常有用的依賴項的依賴的 starter 模塊。簡而言之,添加 starter 應該提供開始使用該庫所需的一切。

提示:如果不需要將自動配置代碼和依賴項管理分離開來,那麼可以將它們合併到一個模塊中。

49.5.1、命名

你應該確保為 starter 提供正確的名稱空間。不要用 spring-boot 啟動模塊名,即使使用不同的 Maven groupId。我們未來可能會為你自動配置的東西提供官方支持。

根據經驗,你應該在 starter 後面命名一個組合模塊。例如, 假設您正在為 “acme” 創建 starter,並且你將自動配置模塊命名為 acme-spring-boot-autoconfigure 和 starter acme-spring-boot-starter。如果你只有一個將兩者結合在一起的模塊,請將其命名為 acme-spring-boot-starter。

此外,如果你的 starter 提供配置鍵,請為它們使用唯一的命名空間。特別是,不要在 Spring Boot 使用的命名空間 (如 server、management、 spring 等) 中包含你的鍵。如果你使用相同的命名空間,我們可能會在將來以破壞你的模塊的方式修改這些命名空間。

確保觸發元數據生成,以便你的鍵也可以使用 IDE 幫助。你可能要查看生成元數據 (meta-inf/spring-configuration-metadata.json) ,以確保鍵正確記錄。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor )

49.5.2、autoconfigure 模塊

autoconfigure 模塊包含開始使用庫所需的一切。它還可能包含配置鍵定義(如 @ConfigurationProperties)和任何回調接口,這些接口可用於進一步自定義組件的初始化方式。

提示:你應該將庫的依賴項標記為可選,以便可以更輕鬆地在項目中包含 autoconfigure 模塊。如果這樣做,則默認情況下不提供庫,並且 Spring Boot 會退出。

Spring Boot 使用註解處理器採集元數據文件(META-INF/spring-autoconfigure-metadata.properties)中自動配置的條件。如果該文件存在,它將用於急切地過濾不匹配的自動配置,這將提高啟動時間。建議在包含自動配置的模塊中添加以下依賴項:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code><dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-autoconfigure-processor/<artifactid>
<optional>true/<optional>
/<dependency>/<code>

對於 Gradle 4.5 和更早版本,應該在 compileOnly 配置中聲明依賴項,如下面示例所示:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>dependencies {
compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}/<code>

對於 Gradle4.6 及更高版本,應該在 annotationProcessor 配置中聲明依賴項,如下面示例所示:

Spring Boot中文參考指南(2.1.6)49.4、測試你的自動配置

<code>dependencies {
annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}/<code>

49.5.3、Starter 模塊

starter 實際上是一個空 jar。它的唯一目的是提供使用庫所必要的依賴項。你可以把它看作是開始需要做的事情的一種固執己見的觀點。

不要對添加了 starter 的項目做出假設。如果你正在自動配置的庫通常需要其他 starter,請也提及它們。如果可選依賴項的數量很高,提供一組合適的默認依賴項可能會很困難,因為你應該避免包含對庫的典型使用不必要的依賴項。換句話說,你不應該包括可選的依賴項。

註釋:無論哪種方式,starter 都必須直接或間接地引用核心 Spring Boot starter(spring-boot-starter)(即,如果 starter 依賴於另一個 starter,則無需添加)。如果一個項目只使用你的自定義 starter 創建,那麼 Spring Boot 的核心功能將受到核心 starter 的支持。

下一篇[未完待續]


分享到:


相關文章: