56 votes

Unité testant un servlet Java

Je voudrais savoir quelle serait la meilleure façon de faire des tests unitaires d'un servlet.

Tester des méthodes internes n’est pas un problème tant qu’elles ne font pas référence au contexte de la servlet, mais qu’en est-il du test des méthodes doGet / doPost ainsi que de la méthode interne qui fait référence au contexte ou utilise des paramètres de session?

Y a-t-il un moyen de faire cela simplement en utilisant des outils classiques tels que JUnit ou de préférence TestNG? Ai-je besoin d'intégrer un serveur Tomcat ou quelque chose du genre?

46voto

Garth Gilmour Points 5219

La plupart du temps je test les Servlets et les JSP de la via de 'Tests d'Intégration" plutôt que de pur Tests Unitaires. Il existe un grand nombre d'add-ons pour JUnit/TestNG disponibles, y compris:

  • HttpUnit (les plus anciennes et les plus connues, de très bas niveau qui peut être bon ou mauvais en fonction de vos besoins)
  • Interface htmlunit (niveau plus élevé que HttpUnit, ce qui est mieux pour de nombreux projets)
  • JWebUnit (se trouve sur le dessus des autres outils de test et tente de les simplifier, - celui que je préfère)
  • WatiJ et le Sélénium (utilisez votre navigateur pour effectuer les tests, ce qui est plus lourd mais réaliste)

C'est un JWebUnit test pour un simple Traitement de la Commande Servlet, qui traite l'entrée de la forme 'orderEntry.html'. Il s'attend à un numéro de client, nom du client et un ou plusieurs articles d'une commande:

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;
}

13voto

Peter Hilton Points 10580

Essayez HttpUnit , même si vous finirez probablement par écrire des tests automatisés qui sont davantage des "tests d'intégration" (d'un module) que des "tests unitaires" (d'une seule classe).

11voto

John Yeary Points 725

J'ai regardé les réponses et pensé que je voudrais poster une solution plus complète que la réalité montre comment faire le test à l'aide d'embedded GlassFish et sa Apache Maven plugin.

J'ai écrit le processus complet sur mon blog à l'Aide de GlassFish 3.1.1 Intégré avec JUnit 4.x et interface htmlunit 2.x et placé le projet complet à télécharger sur Bitbucket ici: image-servlet

J'était à la recherche d'un autre poste sur une image servlet JSP/JSF balises juste avant j'ai vu cette question. Donc, j'ai combiné la solution que j'ai utilisé de l'autre post avec une unité complète en version testée pour ce poste.

Comment faire pour Tester

Apache Maven a un cycle de vie qui inclut test. Je vais l'utiliser avec un autre du cycle de vie des appelés integration-test pour mettre en œuvre ma solution.

  1. Désactiver le cycle de vie standard de tests unitaires dans le plugin surefire.
  2. Ajouter integration-test dans le cadre de l'exécution de la surefire-plugin
  3. Ajouter la GlassFish plugin Maven pour le POM.
  4. Configurer GlassFish à exécuter au cours de l' integration-test cycle de vie.
  5. Exécuter des tests unitaires (tests d'intégration).

GlassFish Plugin

Ajouter ce plugin dans le cadre de l' <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>

Plugin Surefire

Ajouter/modifier le plugin dans le cadre de l' <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>

Interface htmlunit

Ajouter les tests d'intégration, comme l'exemple ci-dessous.

@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();
}

J'ai écrit le processus complet sur mon blog à l'Aide de GlassFish 3.1.1 Intégré avec JUnit 4.x et interface htmlunit 2.x et placé le projet complet à télécharger sur Bitbucket ici: image-servlet

Si vous avez des questions, veuillez laisser un commentaire. Je pense que c'est un exemple complet pour vous d'utiliser comme base de toute analyse, vous êtes planification pour les servlets.

7voto

Marcio Aguiar Points 6715

Êtes-vous en appelant le doPost et méthodes doGet manuellement dans les tests unitaires? Si oui, vous pouvez remplacer le HttpServletRequest méthodes pour fournir les objets fantaisie.

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

     ...
}

Le HttpServletRequestWrapper est un confort de classe Java. Je vous suggère de créer une méthode utilitaire dans vos tests unitaires pour créer la maquette http demandes:

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

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

C'est même mieux de mettre de la fantaisie des méthodes de création dans une base de servlet super-classe et de faire toutes les servlets de tests unitaires pour le prolonger.

6voto

Kris Pruden Points 1284

Mockrunner ( http://mockrunner.sourceforge.net/index.html ) peut le faire. Il fournit un conteneur fictif J2EE pouvant être utilisé pour tester les servlets. Il peut également être utilisé pour tester à l'unité d'autres codes côté serveur tels que les EJB, JDBC, JMS, Struts. Je n'ai utilisé que les capacités JDBC et EJB moi-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X