2012-11-13 66 views
2

單元測試此代碼的最佳方式是什麼?當條件爲真時,我需要爲httpResponse建立sendError()的一致檢查。提前致謝!如何Junit測試具有特定響應的servlet過濾器

編輯:不幸的是,這個過濾器不適用於Spring MVC,所以我的選擇是有限的。

public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain filterchain) throws IOException, ServletException { 

    String ipAddress = request.getRemoteAddr(); 
    if(SomeParameterCheckingFunction ((request))) { 
     logger.error("Error detected! Time: " + new Date().toString() + ", Originating IP: " + ipAddress); 
     if (response instanceof HttpServletResponse){ 
      HttpServletResponse httpResponse = (HttpServletResponse) response; 
      httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN,"You are not allowed to access the server!"); 
     } 
    } 
    filterchain.doFilter(request, response); 
} 

回答

0

一個選項可能是將SomeParameterCheckingFunction的定義從過濾器本身抽出(並在過濾器中使用它)。然後,您可以單獨測試該邏輯。但是,我不確定這對你是否足夠。

另一種選擇可能是使用Mockito測試過濾器類。這將涉及一些勞動力,嘲笑請求,響應,過濾鏈,日誌記錄等。您應該能夠驗證response.sendError()調用之後像這樣(假定的的Mockito靜態導入*方法):

//setup mock with concrete class for instanceof check 
ServletResponse resp = mock(HttpServletResponse.class); 

//define behavior for desired method with void return type. this appears optional for mocks. 
//doNothing().when(resp).sendError(anyInt(), anyString()); 

//your test here, passing in resp  
if(resp instanceof HttpServletResponse) resp.sendError(400, "blah"); 

//verify method was called  
verify(resp).sendError(400, "blah"); 

有可能會或可能不會與HttpUnit來測試你的過濾器的方式,但這可能無法滿足您進行適當的單元測試的需求。

+0

我已經具有針對SomeParameterCheckingFunction(另一個單元測試),所以我可以很容易地模擬它與Mockito。有能力驗證response.sendError()將是一個理想的測試用例,但我完全被困在如何做到這一點。你能告訴我關於如何在過濾器被調用後能夠在junit中驗證response.sendError()的技術嗎? TNX! – hb5fa

0

2018年2月更新:OpenBrace Limited has closed down,其ObMimic產品不再受支持。

下面是如何使用我的ObMimic Servlet API的容器外測試雙精度庫來測試「sendError」的示例。

首先,在給定的doFilter代碼的一些注意事項:

  • 「((請求))」 的大概意思只是 「(請求)」。

  • 「記錄器」的性質沒有顯示出來,所以我現在忽略了這一點,因爲這是無關緊要的。

  • 給定的過濾器將檢查非HTTP請求,但是如果它們被拒絕,則通常的日誌消息被寫入,但是隨後sendError被跳過並執行正常處理。根據你想要做的事情,你可能想要預先拒絕非HTTP請求,或根本不檢查它們,或者做一些其他類型的拒絕來代替「sendError」。現在我假設我們只關心如何測試HTTP請求上的「sendError」。

  • 下面的示例測試表明,即使在調用sendError時,處理仍會直接進入正常的「doFilter」調用。假設這不是故意的,那麼「sendError」後面應該跟一個「return」,或者「doFilter」應該在「else」子句中。

對於下面的示例代碼:

  • 我用的JUnit的測試框架,但它也可以同樣是TestNG的或其他任何東西。

  • 對於「SomeParameterCheckingFunction」,我剛剛使用了一個如果遠程IP地址爲「1.1.1.1」,則返回true。

  • 「sendError」產生顯示給定消息的HTML響應。對於這個例子,我只是檢查響應正文包含給定的消息。如果您想要檢查傳遞給「sendError」的參數值,ObMimic的「Professional Edition」具有「歷史記錄」功能,可以讓您執行此操作。或者,您可以在單獨的響應實例上執行「sendError」,然後檢查響應正文是否完全匹配。

總之,這裏的示例代碼:

package com.openbrace.experiments.examplecode.stackoverflow13365536; 

import static org.junit.Assert.*; 
import com.openbrace.experiments.examplecode.stackoverflow13365536.YourFilter; 
import com.openbrace.obmimic.mimic.servlet.FilterChainMimic; 
import com.openbrace.obmimic.mimic.servlet.FilterConfigMimic; 
import com.openbrace.obmimic.mimic.servlet.ServletMimic; 
import com.openbrace.obmimic.mimic.servlet.http.HttpServletRequestMimic; 
import com.openbrace.obmimic.mimic.servlet.http.HttpServletResponseMimic; 
import com.openbrace.obmimic.support.servlet.EndPoint; 
import org.hamcrest.CoreMatchers; 
import org.junit.Assert; 
import org.junit.Before; 
import org.junit.Test; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

/** 
* Example tests for {@link YourFilter#doFilter(ServletRequest, ServletResponse, 
* FilterChain)}. 
* 
* @author Mike Kaufman, OpenBrace Limited 
*/ 
public class YourFilterTest { 

    /** The filter to be tested by this instance's test. */ 
    private YourFilter filter; 

    /** The "mimic" request to be used in this instance's test. */ 
    private HttpServletRequestMimic request; 

    /** The "mimic" response to be used in this instance's test. */ 
    private HttpServletResponseMimic response; 

    /** The filter chain to be used in this instance's test. */ 
    private FilterChainMimic filterChain; 

    /** 
    * Set up for this instance's test by creating an initialized filter and a 
    * request, response and filter chain for use in the test. 
    * 
    * @throws ServletException if the filter's init method throws such an 
    *  exception. 
    */ 
    @Before 
    public void setUp() throws ServletException { 
     /* 
     * Note that for this example's simple filter and tests: 
     * - We don't need anything particular in the filter's FilterConfig. 
     * - We don't need any particular ServletContext, so we can leave 
     * ObMimic to use its default ServletContext throughout. 
     * - We don't need to retain any references to the filter's FilterConfig 
     * or ServletContext. 
     * - We can use a FilterChainMimic with default values as the filter 
     * chain. This has a ServletMimic as the next thing in the chain, and 
     * ServletMimic keeps a count of the calls to its service method, so 
     * we can use this to check whether the filter chain's doFilter has 
     * been invoked. 
     */ 
     filter = new YourFilter(); 
     filter.init(new FilterConfigMimic()); 
     request = new HttpServletRequestMimic(); 
     response = new HttpServletResponseMimic(); 
     filterChain = new FilterChainMimic(); 
    } 

    /** 
    * Test the doFilter method with an example request for which 
    * SomeParameterCheckingFunction returns true (so that the FORBIDDEN 
    * response should result). 
    * 
    * @throws ServletException if the servlet throws such an exception. 
    * @throws IOException if the servlet throws such an exception. 
    */ 
    @Test 
    public void testYourFilterWithForbiddenRequest() 
      throws ServletException, IOException { 

     // Configure the request so that SomeParameterCheckingFunction will 
     // return true, which for purposes of this example is triggered by a 
     // particular "remote address". 
     request.getMimicState().setRemoteEndPoint(
      new EndPoint(null, "1.1.1.1", null)); 

     // Invoke the doFilter method. 
     filter.doFilter(request, response, filterChain); 

     // Check that the response is now FORBIDDEN, and that its HTML content 
     // does include the expected text message. 
     int responseCode = response.getMimicState().getHttpStatusCode(); 
     String responseBody = response.getMimicState().getBodyContentAsString(); 
     String expectedMessage = "You are not allowed to access the server!"; 
     assertEquals("Response has incorrect status code", 
      HttpServletResponse.SC_FORBIDDEN, responseCode); 
     Assert.assertThat("FORBIDDEN response does not include expected message", 
      responseBody, CoreMatchers.containsString(expectedMessage)); 

     // Check that the filter chain was not invoked. As we've used a 
     // FilterChainMimic with default values, its "target" is a ServletMimic, 
     // so we can just check if there have been any calls to that Servlet. 
     ServletMimic targetServlet 
      = (ServletMimic) filterChain.getMimicState().getTarget(); 
     boolean filterChainInvoked 
      = targetServlet.getMimicState().getServiceCount() > 0; 
     assertFalse("FORBIDDEN response but filterChain.doFilter still called", 
      filterChainInvoked); 

    } 

} 

如果你想嘗試一下,有ObMimic的全部細節,並在ObMimic網站上免費下載。

3

例如使用的Mockito模擬框架時,所提供的doFilter()方法可能是JUnit的測試的使用以下測試例:

@Test 
public void testDoFilter() throws IOException, ServletException { 
    // create the objects to be mocked 
    HttpServletRequest httpServletRequest = mock(HttpServletRequest.class); 
    HttpServletResponse httpServletResponse = mock(HttpServletResponse.class); 
    FilterChain filterChain = mock(FilterChain.class); 
    // mock the getRemoteAddr() response 
    when(httpServletRequest.getRemoteAddr()).thenReturn("198.252.206.16"); 

    AccessFilter accessFilter = new AccessFilter(); 
    accessFilter.doFilter(httpServletRequest, httpServletResponse, 
      filterChain); 

    // verify if a sendError() was performed with the expected values 
    verify(httpServletResponse).sendError(HttpServletResponse.SC_FORBIDDEN, 
      "You are not allowed to access the server!"); 
} 
相關問題