3

このコードを単体テストする最良の方法は何ですか? 条件が真の場合に sendError() を行う httpResponse の一貫したチェックを確立する必要があります。前もって感謝します!

編集: 残念ながら、このフィルターは 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);
}
4

3 に答える 3

7

たとえば、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!");
}
于 2014-11-09T08:50:48.960 に答える
0

1つのオプションは、の定義を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を使用してフィルターをテストする方法がある場合とない場合がありますが、それでは適切な単体テストに対する要望が満たされない場合があります。

于 2012-11-13T20:04:31.120 に答える
0

2018 年 2 月更新: OpenBrace Limited は閉鎖され、その ObMimic 製品はサポートされなくなりました。

これは、サーブレット API のコンテナー外テストダブルのObMimicライブラリを使用して、"sendError" をテストする方法の例です。

最初に、指定された doFilter コードに関するいくつかの注意事項:

  • "((request))" は、おそらく "(request)" という意味です。

  • 「ロガー」の性質は示されていないので、今のところ関係ないので無視しました。

  • 指定されたフィルタは非 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のWeb サイトから無料でダウンロードできます。

于 2013-08-15T18:30:13.570 に答える