RSocket 入門:測試 Spring Boot 回應器

工程 | Ben Wilcock | 2020 年 5 月 25 日 | ...

閱讀時間:約 6 分鐘 編碼時間:約 15 分鐘

如果您一直關注這個系列,到目前為止,您應該已經建構了一個 Spring Boot 原型,展示了 RSocket 中的許多功能。 雖然這段程式碼不是產品程式碼;它只是一個原型,是您 RSocket 之旅的墊腳石。對於產品程式碼,我期望所有常見的品質保證和測試規則都適用。因此,在本次練習中,我將向您展示如何為 RSocket 回應器編寫整合測試,以便您能更接近產品環境。

但首先,我所說的整合測試是什麼意思?

在此上下文中,整合測試是指測試 RSocket 請求者和回應器之間來回的通訊。在這樣的測試中,重要的是要測試架構的每一層,包括網路。

但是,整合測試可能比常規單元測試更昂貴,正是因為您正在測試每一層。它們可能需要更長的時間才能運行,需要多個組件和層,並且可能較不可預測。然而,整合測試還有其他好處,例如檢查您的請求者和回應器是否互相接觸並正確通訊。

您也會注意到,我在本教學中跳過了所有其他形式的測試。要涵蓋每種可能的測試類型需要一整本書!如果您正在尋找更通用的 Spring Boot 應用程式測試入門,請試試 Andy Wilkinson 的這個演講,或Spring Boot 測試文件,或在網路上搜尋「testing spring applications」。

背景介紹就夠了;讓我們開始測試吧!

如果您需要查看程式碼,可以在 GitHub 上找到。如果您想了解本系列文章的其餘部分,它們都列在 Spring 網站上我的頁面中。

步驟 1:建立整合測試

在您的 rsocket-server 專案中,在 /src/test/java/io/pivotal/rsocketserver/ 資料夾中,建立一個新的整合測試類別,名為 RSocketClientToServerITest。最簡單的方法通常是在您的 IDE 內進行。

建議的命名慣例是以後綴 'ITest' 結尾每個整合測試類別名稱。產生的檔名 <your-class-name>ITest.java 更易於閱讀,並允許 Maven 過濾您的整合測試 — 您稍後會使用的一種技術。請務必使用 @SpringBootTest 註解您的新類別,如下所示

@SpringBootTest
public class RSocketClientToServerITest {
  // test code goes here
}

@SpringBootTest 註解允許 Spring Boot 配置您的測試所需的一切,包括 RSocket。它可以節省大量時間和大量配置。

步驟 2:開啟您的 RSocket 連線

您可以透過新增 RSocketRequester 作為全域類別變數,將單個 RSocket 連線用於多個測試,如下所示

private static RSocketRequester requester;

在您的測試運行之前,您必須為此請求者建立一個可運作的連線。來自 JUnit5@BeforeAll 註解非常適合執行這些一次性的設定任務。將以下方法新增至您的類別

    @BeforeAll
    public static void setupOnce(@Autowired RSocketRequester.Builder builder, @Value("${spring.rsocket.server.port}") Integer port) {
        requester = builder
                .connectTcp("localhost", port)
                .block();
    }

您會注意到,此方法簽章期望 Spring Boot 從 Spring 應用程式上下文傳遞一些項目。RSocketRequester.Builder 簡化了 RSocket 連線的建立,並且建立連結需要回應器的連接埠號碼。連接埠號碼來自 application.properties 檔案中的 spring.rsocket.server.port 值。

步驟 3:新增測試

現在請求者已就位;您已準備好新增您的第一個整合測試。在此測試期間會發生兩件事。首先,從請求者到回應器的呼叫,附加了命名的路由和資料。其次,驗證接收到的回應是否完全符合預期。程式碼如下所示

     @Test
     public void testRequestGetsResponse() {
         // Send a request message (1)
          Mono<Message> result = requester
                 .route("request-response")
                 .data(new Message("TEST", "Request"))
                 .retrieveMono(Message.class);
 
        // Verify that the response message contains the expected data (2)
        StepVerifier
                  .create(result)
                  .consumeNextWith(message -> { 
assertThat(message.getOrigin()).isEqualTo(RSocketController.SERVER); assertThat(message.getInteraction()).isEqualTo(RSocketController.RESPONSE);
assertThat(message.getIndex()).isEqualTo(0);})
                 .verifyComplete();
     }

在第一個部分 (1) 中,使用的路由是 "request-response",資料是一個新的 Message 物件。來自回應器(您的 RSocketController)的結果是 Message 類型的 Mono

在第二個部分 (2) 中,StepVerifier 類別檢查 mono 的行為是否符合預期。在 consumeWithNext() 方法中,一個函數使用 AssertJ 的斷言方法檢查傳回訊息的內容。verifyComplete() 方法確保互動按預期完成。

其他互動的測試方式相同。這裡不描述每種互動類型的測試,請查看 GitHub 上的完整測試。

步驟 4:關閉您的 RSocket 連線

測試週期完成後,您可以關閉任何不再需要的資源。在這種情況下,這意味著處置 RSocket 請求者。新增一個方法來執行此操作,並使用 @AfterAll 註解該方法,如下所示

      @AfterAll
      public static void tearDownOnce() {
          requester.rsocket().dispose();
      }

步驟 5:配置 Failsafe

運行整合測試可能需要一段時間,而且它們可能會因意外原因而失敗,例如網路中斷。因此,隔離您的整合測試以便您可以選擇性地運行它們是有意義的。Maven 使用 Failsafe 外掛程式 來實現此目的。

要配置 failsafe,請在您的 pom.xml 中新增以下外掛程式配置。此配置告訴 Maven 使用 failsafe 運行所有以後綴 'ITest.java' 結尾的測試。它還告訴 Maven 在 integration-testverify 生命周期階段中運行這些測試。

<plugins>
<!-- other plugins -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.22.0</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <includes>**/*ITest.java</includes>
        </configuration>
      </plugin>

您也會希望阻止整合測試與您的常規單元測試一起運行,因此請新增以下 surefire 配置以排除它們

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>**/*ITest.java</exclude>
          </excludes>
        </configuration>
      </plugin>
<!-- other plugins -->
</plugins>

步驟 6:運行您的測試

您現在可以在終端機控制台中運行整合測試。Maven 使用 integration-test 目標來達到此目的。

./mvnw clean integration-test

Maven 現在運行您的整合測試,結果會顯示在控制台中。

[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 23.582 s - in io.pivotal.rsocketserver.RSocketClientToServerITest
2020-05-19 10:43:27.512 INFO 39250 --- [extShutdownHook] i.p.rsocketserver.RSocketController : Detaching all remaining clients...
2020-05-19 10:43:27.513 INFO 39250 --- [extShutdownHook] i.p.rsocketserver.RSocketController : Shutting down.
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

還有更多!

您也可以整合測試您的用戶端回應器。所需的程式碼比上面的程式碼稍微複雜。主要是,這涉及建立一個偽造的請求者組件,其中包含與您在此處看到的類似的 StepVerifier 測試。我建議您查看原始碼,而不是逐行描述程式碼。

最終想法

整合測試是產品化路徑上的關鍵組件。透過這種方式測試您的 RSocket 回應器,您可以防止回歸、檢查組件是否正確通訊,並更有信心地將它們交付給您的客戶。

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部