2016年6月15日 星期三

對 Jersey 製作的 RESTful API 做單元測試(一)

在比較完整的專案中,一般都會至少要包含自動化的單元測試
不過 Application 還好,如果是 RESTful API 的話,應該要怎麼測試呢?

原先我自己的想法是使用 JUnit,然後可能是使用內嵌式的 Jetty
讓測試程式執行時,自動打開一台本地端的 Jetty、把專案佈署上去後開始執行測試。
但既有找到的方法(例如 [1]) 感覺整合性都不太高…。
最後想說,也許其實有更簡易的方式,於是變更了關鍵字之後,發現…真的有 XD。
Jersey 原來本身就有涵蓋了對應的測試架構了。

以下是以 Jersey 2 的範例建立最初級的 RESTful API,然後嘗試使用 Jersey 的 Test Framework 來對這個 API 做測試。

    設定 Maven

    pom.xml 裡面除了本來 Jersey 有的內容以外,還必須包含 Test Framework 的套件。
    在這裡因為我喜歡用 Jetty,因此是拿 Jetty 的套件
    如果比較喜歡像是 grizzly2、org.simpleframework.http、…等等的,可以在 [2] 的 26.2 章節中找到對應的 Maven 設定。

    不過題外話,Jetty 的套件在文件 [2] 上寫的版本 2.23.1,其實在 Maven Repository Server 上找不到,因此我目前是用 2.23 版。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <properties>
        <jersey.version>2.23</jersey.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
        </dependency>
        <!-- Unit Test -->
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-jetty</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    其中前 15 行是 Jersey 的範本自動產生的部份,也就是所有 Jersey 相關的套件全都自動套用 2.23 版。
    主要要追加的部份是 23~27 行,jersey-test-framework-provider-jetty 這個套件。

    撰寫 RESTful API

    RESTful API 的部份,完全是 Jersey 範本自動產生的,內容如下:

    @Path("myresource")
    public class MyResource {
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String getIt() {
            return "Got it!";
        }
    }
    撰寫單元測試

    單元測試的範例如下:

    import javax.ws.rs.core.Application;
    
    import org.glassfish.jersey.server.ResourceConfig;
    import org.glassfish.jersey.test.JerseyTest;
    import org.junit.Assert;
    import org.junit.Test;
    
    public class MyTest extends JerseyTest {
        @Override
        protected Application configure() {
                return new ResourceConfig(MyResource.class);
        }
        
        @Test
        public void test() {
            String hello = target("myresource").request().get(String.class);
            Assert.assertEquals("Got it!", hello);
        }
    }

    單元測試的部份,必須要繼承 org.glassfish.jersey.test.JerseyTest 這個類別,並且一定要覆寫 configure() 方法。
    覆寫 confugire() 的目的,就是為了讓 JerseyTest 能夠知道需要被測試的 RESTful API 在哪裡
    它才能夠正常地幫忙建立假的 endpoint。

    而測試的時候,也必須使用 JerseyTest 內建提供的存取方法,而不是自己直接用像是 Appache HTTP Client 去存取 localhost。
    最後要執行時,就用一般 JUnit 的方法執行即可。

    相關資源

    下篇:對 Jersey 製作的 RESTful API 做單元測試(二):啟用 Servlet

    參考資料
    1. Jetty WTP Plugin/Jetty WTP Dynamic Web Project
    2. Chapter 26. Jersey Test Framework

    沒有留言: