85 Stimmen

Erstellen einer Mock HttpServletRequest aus einer Url-Zeichenfolge?

Ich habe einen Dienst, der einige Arbeit auf ein HttpServletRequest-Objekt, speziell mit der request.getParameterMap und request.getParameter, ein Objekt zu konstruieren tut.

Ich habe mich gefragt, ob es eine einfache Möglichkeit gibt, eine bereitgestellte URL in Form einer Zeichenfolge zu übernehmen, z. B.

String url = "http://www.example.com/?param1=value1&param";

und einfach konvertieren Sie es in ein HttpServletRequest-Objekt, so dass ich es mit meinen Unit-Tests testen kann? Oder zumindest nur so, dass request.getParameterMap und request.getParameter richtig funktionieren?

67voto

Guito Punkte 1091

Hier ist es, wie man MockHttpServletRequest verwenden:

// given
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServerName("www.example.com");
request.setRequestURI("/foo");
request.setQueryString("param1=value1&param");

// when
String url = request.getRequestURL() + '?' + request.getQueryString(); // assuming there is always queryString.

// then
assertThat(url, is("http://www.example.com:80/foo?param1=value1&param"));

1 Stimmen

Mit dieser MockHttpServletRequest tatsächlich tut die Arbeit, wie ich gerade eine voll funktionsfähige HttpServletRequest benötigt

3 Stimmen

Beachten Sie, dass beim Setzen des queryString der Parameter Map in MockHttpServletRequest nicht automatisch aktualisiert wird. Wenn Sie also request.getParameter() in Ihrem Code verwenden, müssen Sie ihn zuerst explizit in der Testeinrichtung setzen, auch wenn dies zunächst redundant erscheinen mag.

0 Stimmen

Das habe ich auch festgestellt. Query-string und Parameter scheinen nicht zu synchronisieren

53voto

pap Punkte 26116

Der Frühling hat MockHttpServletRequest in seinem Frühjahrs-Testmodul.

Wenn Sie Maven verwenden, müssen Sie möglicherweise die entsprechende Abhängigkeit zu Ihrem pom.xml . Sie finden spring-test unter mvnrepository.com .

40voto

Matt Ball Punkte 343109

Einfachste Möglichkeiten zur Verhöhnung einer HttpServletRequest :

  1. Erstellen Sie eine anonyme Unterklasse:

    HttpServletRequest mock = new HttpServletRequest ()
    {
        private final Map<String, String[]> params = /* whatever */
    
        public Map<String, String[]> getParameterMap()
        {
            return params;
        }
    
        public String getParameter(String name)
        {
            String[] matches = params.get(name);
            if (matches == null || matches.length == 0) return null;
            return matches[0];
        }
    
        // TODO *many* methods to implement here
    };
  2. Verwenden Sie jMock , Mockito oder ein anderes universelles Mocking-Framework:

    HttpServletRequest mock = context.mock(HttpServletRequest.class); // jMock
    HttpServletRequest mock2 = Mockito.mock(HttpServletRequest.class); // Mockito
  3. Verwenden Sie die HttpUnit ServletUnit und machen Sie sich nicht über den Antrag lustig.

0 Stimmen

Was ist das WHATEVER in den Kommentaren?

0 Stimmen

@ruby_object was auch immer eine Map von Parametern ist, die im Unit-Test geparst werden sollen. Wenn wir URL/?search=xyz übergeben, dann wird dieses whatever die Zuordnung der Suche nach xyz enthalten.

0 Stimmen

Lösung 1 wird nicht funktionieren, da HttpServletRequest kann nicht konstruiert werden.

4voto

Rocky Pulley Punkte 21329

In der Regel testet man solche Dinge in einem Integrationstest, der tatsächlich eine Verbindung zu einem Dienst herstellt. In einem Unit-Test sollten Sie die Objekte testen, die von den doGet/doPost-Methoden Ihres Servlets verwendet werden.

Im Allgemeinen möchten Sie nicht viel Code in Ihren Servlet-Methoden haben. Sie möchten eine Bean-Klasse erstellen, um Operationen zu handhaben, und ihr Ihre eigenen Objekte und nicht Servlet-API-Objekte übergeben.

1 Stimmen

Andererseits: Warum sollten Sie sich die Gelegenheit entgehen lassen, die Testabdeckung (d. h. die Robustheit Ihres Codes) zu erhöhen, nur weil die Methode zufällig einen bestimmten Parametertyp als Eingabe akzeptiert?

1 Stimmen

Es hängt davon ab, versuchen Sie, Unit-Test der Servlet-API oder versuchen Sie, Unit-Test Ihren eigenen Code?

5 Stimmen

"Im Allgemeinen" wollen Sie keinen Code in Ihren Servlet-Methoden haben. In der Praxis werden Sie das immer tun. Und Sie werden Helper-Klassen, Utility-Methoden, Parsing, Validierungen, Modellübersetzungen und manchmal sogar Business-Logik (der Horror!) haben. Und weil das so ist, wollen Sie diese Methoden natürlich auch testen. Aus diesem Grund werden Sie Servlet-Anfragen nachbilden wollen, um gut definierte Testszenarien zu erstellen. Mocking der Servlet-API ist genau das Gegenteil von Testen. Es bedeutet, dass sie vollständig aus dem Testfall entfernt wird.

2voto

mel3kings Punkte 7889

Für diejenigen, die eine Möglichkeit suchen, sich über POST HttpServletRequest mit Json Nutzdaten, die unten ist in Kotlin, aber der Schlüssel nehmen hier ist die DelegatingServetInputStream wenn Sie sich über die request.getInputStream von der HttpServletRequest

@Mock
private lateinit var request: HttpServletRequest

@Mock
private lateinit var response: HttpServletResponse

@Mock
private lateinit var chain: FilterChain

@InjectMocks
private lateinit var filter: ValidationFilter

@Test
fun `continue filter chain with valid json payload`() {
    val payload = """{
      "firstName":"aB",
      "middleName":"asdadsa",
      "lastName":"asdsada",
      "dob":null,
      "gender":"male"
    }""".trimMargin()

    whenever(request.requestURL).
        thenReturn(StringBuffer("/profile/personal-details"))
    whenever(request.method).
        thenReturn("PUT")
    whenever(request.inputStream).
        thenReturn(DelegatingServletInputStream(ByteArrayInputStream(payload.toByteArray())))

    filter.doFilter(request, response, chain)

    verify(chain).doFilter(request, response)
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X