Domanda

Vorrei sapere quale sarebbe il modo migliore per fare i test di unità di una servlet.

Test metodi interni non è un problema, purché non fare riferimento al contesto servlet, ma che cosa circa la prova del doGet/doPost metodi come il metodo interno che si riferiscono al contesto o fare uso di parametri di sessione?

C'è un modo per fare questo, semplicemente utilizzando i classici strumenti come JUnit, o preferibilmente TestNG?Ho bisogno di incorporare un server tomcat o qualcosa di simile?

È stato utile?

Soluzione

Provare HttpUnit, anche se alla fine probabilmente la scrittura di test automatizzati che sono piu 'di test di integrazione' (di modulo) di 'unità di test (di una sola classe).

Altri suggerimenti

La maggior parte del tempo faccio la prova di Servlet e JSP tramite "Test di Integrazione', piuttosto che la pura Unità di Test.Ci sono un gran numero di add-ons per JUnit/TestNG, tra cui:

  • HttpUnit (le più antiche e rinomate, livello molto basso, che può essere buona o cattiva a seconda delle vostre esigenze)
  • HtmlUnit (livello superiore rispetto HttpUnit, che è meglio per molti progetti)
  • JWebUnit (si siede sulla cima di altri strumenti di test e cerca di semplificare loro - quello che preferisco)
  • WatiJ e il Selenio (utilizzare il browser per fare il test, che è più pesante, ma realistico)

Questo è un JWebUnit di prova per un semplice Ordine di Elaborazione Servlet che elabora l'input dal modulo 'orderEntry.html'.Si aspetta un id utente, nome di un cliente e di uno o più elementi di ordine:

public class OrdersPageTest {
    private static final String WEBSITE_URL = "http://localhost:8080/demo1";

    @Before
    public void start() {
        webTester = new WebTester();
        webTester.setTestingEngineKey(TestingEngineRegistry.TESTING_ENGINE_HTMLUNIT);
        webTester.getTestContext().setBaseUrl(WEBSITE_URL);
    }
    @Test
    public void sanity() throws Exception {
        webTester.beginAt("/orderEntry.html");
        webTester.assertTitleEquals("Order Entry Form");
    }
    @Test
    public void idIsRequired() throws Exception {
        webTester.beginAt("/orderEntry.html");
        webTester.submit();
        webTester.assertTextPresent("ID Missing!");
    }
    @Test
    public void nameIsRequired() throws Exception {
        webTester.beginAt("/orderEntry.html");
        webTester.setTextField("id","AB12");
        webTester.submit();
        webTester.assertTextPresent("Name Missing!");
    }
    @Test
    public void validOrderSucceeds() throws Exception {
        webTester.beginAt("/orderEntry.html");
        webTester.setTextField("id","AB12");
        webTester.setTextField("name","Joe Bloggs");

        //fill in order line one
        webTester.setTextField("lineOneItemNumber", "AA");
        webTester.setTextField("lineOneQuantity", "12");
        webTester.setTextField("lineOneUnitPrice", "3.4");

        //fill in order line two
        webTester.setTextField("lineTwoItemNumber", "BB");
        webTester.setTextField("lineTwoQuantity", "14");
        webTester.setTextField("lineTwoUnitPrice", "5.6");

        webTester.submit();
        webTester.assertTextPresent("Total: 119.20");
    }
    private WebTester webTester;
}

Ho guardato le risposte e ho pensato che vorrei postare una soluzione più completa che in realtà viene illustrato come eseguire il test utilizzando embedded GlassFish e i suoi Apache Maven plugin.

Ho scritto un processo completo sul mio blog Utilizzando GlassFish 3.1.1 Incorporato con JUnit 4.x e HtmlUnit 2.x e inserito il progetto completo per il download su Bitbucket qui: immagine-servlet

Stavo guardando un altro post su di un'immagine servlet JSP/JSF tag poco prima ho visto questa domanda.Così ho combinato con la soluzione che ho usato da altri post con una unità completa testato la versione per questo post.

Come Test

Apache Maven ha un ben definito ciclo di vita che include test.Io uso questo, insieme con un altro ciclo di vita del chiamato integration-test per implementare la soluzione.

  1. Disattivare il ciclo standard di test di unità in surefire plugin.
  2. Aggiungere integration-test come parte delle esecuzioni del surefire-plugin
  3. Aggiungere il GlassFish Maven plugin per il POM.
  4. Configurare GlassFish eseguire durante il integration-test ciclo di vita.
  5. Eseguire unit test (test di integrazione).

GlassFish Plugin

Aggiungere questo plugin come parte del <build>.

        <plugin>
            <groupId>org.glassfish</groupId>
            <artifactId>maven-embedded-glassfish-plugin</artifactId>
            <version>3.1.1</version>
            <configuration>
                <!-- This sets the path to use the war file we have built in the target directory -->
                <app>target/${project.build.finalName}</app>
                <port>8080</port>
                <!-- This sets the context root, e.g. http://localhost:8080/test/ -->
                <contextRoot>test</contextRoot>
                <!-- This deletes the temporary files during GlassFish shutdown. -->
                <autoDelete>true</autoDelete>
            </configuration>
            <executions>
                <execution>
                    <id>start</id>
                    <!-- We implement the integration testing by setting up our GlassFish instance to start and deploy our application. -->
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>start</goal>
                        <goal>deploy</goal>
                    </goals>
                </execution>
                <execution>
                    <id>stop</id>
                    <!-- After integration testing we undeploy the application and shutdown GlassFish gracefully. -->
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>undeploy</goal>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Surefire Plugin

Aggiungere/modificare il plugin come parte del <build>.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.12.4</version>
            <!-- We are skipping the default test lifecycle and will test later during integration-test -->
            <configuration>
                <skip>true</skip>
            </configuration>
            <executions>
                <execution>
                    <phase>integration-test</phase>
                    <goals>
                        <!-- During the integration test we will execute surefire:test -->
                        <goal>test</goal>
                    </goals>
                    <configuration>
                        <!-- This enables the tests which were disabled previously. -->
                        <skip>false</skip>
                    </configuration>
                </execution>
            </executions>
        </plugin>

HTMLUnit

Aggiungere i test di integrazione come nell'esempio qui sotto.

@Test
public void badRequest() throws IOException {
    webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
    webClient.getOptions().setPrintContentOnFailingStatusCode(false);
    final HtmlPage page = webClient.getPage("http://localhost:8080/test/images/");
    final WebResponse response = page.getWebResponse();
    assertEquals(400, response.getStatusCode());
    assertEquals("An image name is required.", response.getStatusMessage());
    webClient.getOptions().setThrowExceptionOnFailingStatusCode(true);
    webClient.getOptions().setPrintContentOnFailingStatusCode(true);
    webClient.closeAllWindows();
}

Ho scritto un processo completo sul mio blog Utilizzando GlassFish 3.1.1 Incorporato con JUnit 4.x e HtmlUnit 2.x e inserito il progetto completo per il download su Bitbucket qui: immagine-servlet

Se avete domande, si prega di lasciare un commento.Penso che questo sia un esempio completo per utilizzare come base di qualsiasi laboratorio di pianificazione per i servlets.

Chiama il doPost e metodi doGet manualmente nel test di unità?Se è così si può ignorare il HttpServletRequest metodi per fornire oggetti fittizi.

myServlet.doGet(new HttpServletRequestWrapper() {
     public HttpSession getSession() {
         return mockSession;
     }

     ...
}

Il HttpServletRequestWrapper è una comodità classe Java.Ti consiglio di creare un programma di utilità di metodi di test di unità per creare il finto richieste http:

public void testSomething() {
    myServlet.doGet(createMockRequest(), createMockResponse());
}

protected HttpServletRequest createMockRequest() {
   HttpServletRequest request = new HttpServletRequestWrapper() {
        //overrided methods   
   }
}

Ancora meglio sarebbe mettere il finto metodi di creazione di una base servlet superclasse e fare tutti i servlets test di unità di ampliamento.

Mockrunner (http://mockrunner.sourceforge.net/index.html può fare questo.Esso fornisce un finto J2EE contenitore che può essere utilizzato per verificare la Servlet.Può essere utilizzato anche per di unit test per altri codice lato server come Ejb, JDBC, JMS, Struts.Ho usato solo il JDBC, EJB e capacità di me.

Questa implementazione di un test JUnit per servlet doPost() il metodo si basa solo sul Mockito biblioteca per beffardo le istanze di HttpRequest, HttpResponse, HttpSession, ServletResponse e RequestDispatcher.Sostituire il parametro di chiavi e JavaBean istanza con quelli che corrispondono ai valori di riferimento nel relativo file JSP, da cui doPost() viene chiamato.

Mockito Maven dipendenza:

<dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.9.5</version>
</dependency>

JUnit test:

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;

/**
 * Unit tests for the {@code StockSearchServlet} class.
 * @author Bob Basmaji
 */
public class StockSearchServletTest extends HttpServlet {
    // private fields of this class
    private static HttpServletRequest request;
    private static HttpServletResponse response;
    private static StockSearchServlet servlet;
    private static final String SYMBOL_PARAMETER_KEY = "symbol";
    private static final String STARTRANGE_PARAMETER_KEY = "startRange";
    private static final String ENDRANGE_PARAMETER_KEY = "endRange";
    private static final String INTERVAL_PARAMETER_KEY = "interval";
    private static final String SERVICETYPE_PARAMETER_KEY = "serviceType";

    /**
     * Sets up the logic common to each test in this class
     */
    @Before
    public final void setUp() {
        request = mock(HttpServletRequest.class);
        response = mock(HttpServletResponse.class);

        when(request.getParameter("symbol"))
                .thenReturn("AAPL");

        when(request.getParameter("startRange"))
                .thenReturn("2016-04-23 00:00:00");

        when(request.getParameter("endRange"))
                .thenReturn("2016-07-23 00:00:00");

        when(request.getParameter("interval"))
                .thenReturn("DAY");

        when(request.getParameter("serviceType"))
                .thenReturn("WEB");

        String symbol = request.getParameter(SYMBOL_PARAMETER_KEY);
        String startRange = request.getParameter(STARTRANGE_PARAMETER_KEY);
        String endRange = request.getParameter(ENDRANGE_PARAMETER_KEY);
        String interval = request.getParameter(INTERVAL_PARAMETER_KEY);
        String serviceType = request.getParameter(SERVICETYPE_PARAMETER_KEY);

        HttpSession session = mock(HttpSession.class);
        when(request.getSession()).thenReturn(session);
        final ServletContext servletContext = mock(ServletContext.class);
        RequestDispatcher dispatcher = mock(RequestDispatcher.class);
        when(servletContext.getRequestDispatcher("/stocksearchResults.jsp")).thenReturn(dispatcher);
        servlet = new StockSearchServlet() {
            public ServletContext getServletContext() {
                return servletContext; // return the mock
            }
        };

        StockSearchBean search = new StockSearchBean(symbol, startRange, endRange, interval);
        try {
            switch (serviceType) {
                case ("BASIC"):
                    search.processData(ServiceType.BASIC);
                    break;
                case ("DATABASE"):
                    search.processData(ServiceType.DATABASE);
                    break;
                case ("WEB"):
                    search.processData(ServiceType.WEB);
                    break;
                default:
                    search.processData(ServiceType.WEB);
            }
        } catch (StockServiceException e) {
            throw new RuntimeException(e.getMessage());
        }
        session.setAttribute("search", search);
    }

    /**
     * Verifies that the doPost method throws an exception when passed null arguments
     * @throws ServletException
     * @throws IOException
     */
    @Test(expected = NullPointerException.class)
    public final void testDoPostPositive() throws ServletException, IOException {
        servlet.doPost(null, null);
    }

    /**
     * Verifies that the doPost method runs without exception
     * @throws ServletException
     * @throws IOException
     */
    @Test
    public final void testDoPostNegative() throws ServletException, IOException {
        boolean throwsException = false;
        try {
            servlet.doPost(request, response);
        } catch (Exception e) {
            throwsException = true;
        }
        assertFalse("doPost throws an exception", throwsException);
    }
}

Aggiornamento Febbraio 2018: OpenBrace Limited ha chiuso, e la sua ObMimic prodotto non è più supportato.

Un'altra soluzione è usare il mio ObMimic la biblioteca, che è specificamente progettato per i test di unità di servlet.Esso fornisce completa pianura-implementazioni Java di tutte le Servlet API delle classi, è possibile configurare e controllare quanto necessario per i test.

Si può infatti utilizzare per chiamare direttamente doGet/doPost metodi di test JUnit o TestNG, e per testare tutti i metodi interni, anche se si riferiscono alla ServletContext o utilizzare i parametri di sessione (o qualsiasi altra Servlet API caratteristiche).

Questo non ha bisogno di un esterno o incorporato contenitore, non si limitano a una più ampia HTTP-based "integrazione" delle prove, e a differenza di general-purpose prende in giro è pieno di Servlet API comportamento "cotto", quindi il test può essere "stato"piuttosto che del "interazione"(per esempio, l'il test non è necessario fare affidamento sui precisa sequenza delle Servlet API chiamate effettuate dal codice, né le proprie aspettative di come la Servlet API rispondere a ogni chiamata).

C'è un semplice esempio nella mia risposta alla Come prova la mia servlet utilizzo di JUnit.Per tutti i dettagli e il download gratuito di vedere il ObMimic sito web.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top