Jersey 中使用 Jersey Test Framework 做測試時
如果遇到需要使用 Servlet 的狀況,例如使用了 @Context HttpServletRequest request
可能就會注意到,HttpServletRequest 這類應該要自動被注入的東西,在測試時都沒有被注入
因此會發生像是 NullPointerException 等等的錯誤。
雖然有不少網友有去 Jersey 社群詢問或直接開 bug
但官方開發人員的回應是表示這並沒有違背設計,因此也沒有打算要修復。
至於沒有違背設計的原因,可以參考 [6],實際上預設 JerseyTest 會打開的伺服器,僅包含 HTTP container
因此對於 Servlet 注入所需要的 Servlet container 沒有任何反應。
如果想要使用 Servlet 的話,依照官方文件 [6] 的描述,應該改用 GrizzlyWebTestContainerFactory 去提供 test container。
要使用 GrizzlyWebTestContainerFactory,首先當然是 Maven 的設定必須使用 Grizzly
因此必須加上這樣的 dependancy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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.test-framework.providers</ groupId > < artifactId >jersey-test-framework-provider-grizzly2</ artifactId > < scope >test</ scope > </ dependency > </ dependencies > |
在上述的 pom.xml 中,指定了會使用 Grizzly2 來提供 test container 服務,並且使用的版本是 2.23。
除了 Maven 以外,在程式碼的部份也需要做一些額外的設定,以要求使用具有 Servlet 功能的 container。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class MyTest extends JerseyTest { @Override protected TestContainerFactory getTestContainerFactory() { return new GrizzlyWebTestContainerFactory(); } @Override protected DeploymentContext configureDeployment() { ResourceConfig config = new ResourceConfig(MyRestfulApi. class ); return ServletDeploymentContext .forServlet( new ServletContainer(config)) .build(); } @Test public void testServlet () { Response response = target( "/" ) .queryParam( "a" , 1 ) .queryParam( "b" , "test" ) .request() .get(Response. class ); Assert.assertEquals( 200 , response.getStatus()); } } @Path ( "/" ) @Produces public class MyRestfulApi { @GET public Response test ( @Context HttpServletRequest request) { System.out.println( "Request URL: " + request.getRequestURL().toString()); System.out.println( "Queries: " + request.getQueryString()); return Response.ok().build(); } } |
在上述的程式碼中,有兩個類別,MyRestfulApi 是撰寫的 Restful API,而 MyTest 則是測試的程式。
在 RESTful API 中,做的事情只是單純把 Request 的網址和參數印出來而已。
而測試程式 MyTest,則是透過 Override 覆寫了兩個 method
用來指定要使用具有 Servlet 功能的 container,並且 context 也要以 Servlet 的形式佈署
這樣才能順利地讓 Servlet 功能正常運作。
接著在測試案例 testServlet() 中,就產生一個會送出兩個 query parameters 的 HTTP request 給 MyRestfulApi
並且檢查回應的 HTTP status code 是否為 200。
真正執行上述的測試程式時,console 會印出下列的結果,表示 Servlet 確實正常在運作。
1 2 |
Request URL: http://localhost:9998/ Queries: a=1&b=test |
相關資源
上篇:對 Jersey 製作的 RESTful API 做單元測試(一)
參考資料
- jersey2 Unit testing,HttpServletRequest is null
- Problems running JerseyTest when dealing with HttpServletResponse
- Injection of HttpServletRequest when using JerseyTest does not work
- HttpServletRequest always null on test case
- JerseyTest using GrizzlyWebTestContainerFactory in Jersey 2.13
- 26.2. Supported Containers
沒有留言:
張貼留言