一文教會你如何在 Spring 中進行集成測試,太贊了

  • 2020 年 4 月 10 日
  • 筆記

不得不說,測試真的是太重要了!但並不是所有的開發者都這樣認為,這種感覺在我回到洛陽後尤其強烈。竟然有團隊成員不經測試就把程式碼提交到程式碼庫,並且是會報錯的那種,我天吶,遇到這種隊友我也是醉了。

我之前是在一家日企工作,他們非常注重測試,佔用的時間比程式碼編寫的時間多多了。從單元測試到集成測試,所有的測試結果都要整理成文檔保存下來,哪怕你覺得完全沒有必要。但正是這種一絲不苟的態度,成就了日企軟體高品質的美譽。

單元測試通常比較簡單,對運行環境的依賴性不強。但集成測試就完全不同了,需要整個項目是能夠跑起來的,比如說需要資料庫是連接的,網路是通暢的等等。

集成測試最簡單的形式是:把兩個已經測試過的單元組合成一個組件,測試它們之間的介面。從這一層意義上講,組件是指多個單元的集成聚合。在現實方案中,許多單元組合成組件,而這些組件又聚合為程式的更大部分。方法是測試片段的組合,並最終擴展成進程,將模組與其他組的模組一起測試。最後,將構成進程的所有模組一起測試。

Spring 提供了 Spring TestContex Framework 來支援集成測試,它不依賴於特定的測試框架,因此你可以選擇 Junit,也可以選擇 TestNG。本文選擇 Junit,因此需要先將 Junit 和 Spring TestContex Framework 的依賴添加到 pom.xml 文件中。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.2.RELEASE</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

準備工作完成後,來考慮這樣一個場景,我們需要同時為開發環境和生產環境維護數據源配置,因此我們先創建一個公共的介面 Datasource,內容如下所示:

public interface Datasource {
    public void setup();
}

新建 DevDatasource 類,實現 Datasource 介面,該類用於為開發環境配置數據源,內容如下:

@Component
@Profile("dev")
public class DevDatasource implements Datasource {
    @Override
    public void setup() {
        System.out.println("開發環境");
    }
}

@Component 註解用於為 Spring 容器注入一個通用的 Bean 組件。@Profile 註解用於標識不同環境下要實例化的 Bean,字元串「dev」 表示該組件用於開發環境。

新建 ProdDatasource 類,實現 Datasource 介面,該類用於為正式運行環境配置數據源,內容如下:

@Component
@Profile("prod")
public class ProdDatasource implements Datasource {
    @Override
    public void setup() {
        System.out.println("正式環境");
    }
}

新建配置類 SpringTestConfig,內容如下:

@Configuration
@ComponentScan("test")
public class SpringTestConfig {
}

@Configuration 註解表示當前類為一個配置類,@ComponentScan 註解用於指定掃描路徑,該路徑下的 Bean 將會自動裝配到 Spring 容器中。

基於 Maven 構建的項目默認有兩個測試目錄,src/test/java 和 src/test/resources,分別對應於 src/main/java 和 src/main/resources。前者用於測試項目源碼,後者用於測試項目資源。

我們在 src/test/java 目錄下新建測試類 DevTest,內容如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("dev")
@ContextConfiguration(classes = { SpringTestConfig.class })
public class DevTest {
    @Autowired
    Datasource datasource;

    @Test
    public void testSpringProfiles() {
        Assert.assertTrue(datasource instanceof DevDatasource);
    }
}

1)@RunWith 註解用於指定 Junit 運行環境,是 Junit 提供給其他框架測試環境的介面擴展,Spring 提供了 org.springframework.test.context.junit4.SpringJUnit4ClassRunner 作為 Junit 測試環境。

2)@ActiveProfile 註解用於指定哪個配置文件處於活動狀態,本例為開發環境「dev」。

3)@ContextConfiguration 註解用於指定配置類,本例為 SpringTestConfig 類。

4)@Autowired 註解用於指定 Spring 要自動裝配的 Bean。

5)@Test 註解用於表示當前方法為 Junit 測試方法。

程式運行的結果如下圖所示:

再新建一個測試類 ProdTest,內容如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("prod")
@ContextConfiguration(classes = { SpringTestConfig.class })
public class ProdTest {

    @Autowired
    Datasource datasource;

    @Autowired
    Environment environment;

    @Test
    public void testSpringProfiles() {
        for (String profileName : environment.getActiveProfiles()) {
            System.out.println("當前激活的 profile - " + profileName);
        }
        Assert.assertTrue(datasource instanceof ProdDatasource);
    }
}

這次使用 @ActiveProfiles("prod") 註解指定當前環境為正式運行下的環境。本例中我們裝配了一個新的 Bean environment,使用它的 getActiveProfiles() 方法可以獲取當前激活的 Profile。程式運行的結果如下圖所示:

好了,我親愛的讀者朋友,以上就是本文的全部內容了,是不是感覺在 Spring 中進行集成測試還是挺簡單的?如果覺得文章對你有點幫助,請微信搜索「 沉默王二 」第一時間閱讀。示例程式碼已經上傳到 GitHub,傳送門~

我是沉默王二,一枚有趣的程式設計師。原創不易,莫要白票,請你為本文點個贊吧,這將是我寫作更多優質文章的最強動力。