Question

Je suis actuellement à la recherche de moyens de créer des tests automatisés pour un JAX-RS (API Java pour les services Web basés sur RESTful).

J'ai essentiellement besoin d'un moyen de lui envoyer certaines entrées et de vérifier que je reçois les réponses attendues. Je préférerais le faire via JUnit, mais je ne sais pas comment cela peut être réalisé.

Quelle approche utilisez-vous pour tester vos services Web?

Mise à jour: Comme l'entzik l'a souligné, le découplage du service Web de la logique métier me permet de tester la logique métier à l'aide d'unités. Cependant, je souhaite également tester les codes d’état HTTP corrects, etc.

Était-ce utile?

La solution

Jersey est fourni avec une excellente API client RESTful qui facilite grandement la rédaction de tests unitaires. Voir les tests unitaires dans les exemples fournis avec Jersey. Nous utilisons cette approche pour tester la prise en charge REST dans Apache Camel , si vous êtes intéressé, le scénarios de test êtes ici

Autres conseils

Vous pouvez essayer REST Assured , ce qui le rend très simple pour tester les services REST et valider la réponse en Java (avec JUnit ou TestNG).

Comme l'a dit James; Il existe un structure de test pour Jersey. Voici un exemple simple: bonjour le monde:

pom.xml pour l'intégration maven. Lorsque vous exécutez mvn test . Les cadres démarrent un conteneur grizzly. Vous pouvez utiliser jetty ou tomcat en modifiant les dépendances.

...
<dependencies>
  <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.16</version>
  </dependency>

  <dependency>
    <groupId>org.glassfish.jersey.test-framework</groupId>
    <artifactId>jersey-test-framework-core</artifactId>
    <version>2.16</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.16</version>
    <scope>test</scope>
  </dependency>
</dependencies>
...

ExampleApp.java

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class ExampleApp extends Application {

}

HelloWorld.java

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/")
public final class HelloWorld {

    @GET
    @Path("/hello")
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHelloWorld() {

        return "Hello World!";
    }
}

HelloWorldTest.java

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.core.Application;
import static org.junit.Assert.assertEquals;

public class HelloWorldTest extends JerseyTest {

    @Test
    public void testSayHello() {

        final String hello = target("hello").request().get(String.class);

        assertEquals("Hello World!", hello);
    }

    @Override
    protected Application configure() {

        return new ResourceConfig(HelloWorld.class);
    }
}

Vous pouvez consulter cet exemple d'application.

Bien que ce soit trop tard à partir de la date d’affichage de la question, cela a semblé utile pour d’autres qui ont une question similaire. Jersey est livré avec un framework de test appelé Framework de test de Jersey qui vous permet de tester votre RESTful. Service Web, y compris les codes d’état de la réponse. Vous pouvez l'utiliser pour exécuter vos tests sur des conteneurs légers tels que Grizzly, HTTPServer et / ou EmbeddedGlassFish. En outre, la structure peut être utilisée pour exécuter vos tests sur un conteneur Web standard tel que GlassFish ou Tomcat.

Vous avez probablement écrit du code java qui implémente votre logique métier, puis vous avez généré le point de terminaison des services Web.

Il est important de tester indépendamment votre logique métier. Comme c'est du code Java pur, vous pouvez le faire avec des tests JUnit réguliers.

Maintenant, comme la partie services Web n’est qu’un point final, vous voulez vous assurer que la plomberie générée (embouts, etc.) est synchronisée avec votre code java. vous pouvez le faire en écrivant des tests JUnit qui invoquent les clients Java du service Web générés. Cela vous permettra de savoir quand vous modifiez vos signatures Java sans mettre à jour le contenu des services Web.

Si la plomberie de vos services Web est générée automatiquement par votre système de construction à chaque construction, il peut ne pas être nécessaire de tester les points de terminaison (en supposant que tout est généré correctement). Cela dépend de votre niveau de paranoïa.

J'utilise le HTTPClient (http://hc.apache.org/) d'Apache pour appeler les services restants. . La bibliothèque du client HTTP vous permet d'effectuer facilement des opérations get, post ou autres, selon vos besoins. Si votre service utilise JAXB for xml binding, vous pouvez créer un JAXBContext pour sérialiser et désérialiser les entrées et les sorties de la requête HTTP.

Consultez le générateur de client Alchemy rest . Cela peut générer une implémentation de proxy pour votre classe de service Web JAX-RS en utilisant un client jersey derrière la scène. Effectivement, vous appellerez vos méthodes de service Web de simples méthodes Java à partir de vos tests unitaires. Gère également l’authentification http.

Il n'y a pas de génération de code impliquée si vous devez simplement exécuter des tests pour que ce soit pratique.

Avertissement: je suis l'auteur de cette bibliothèque.

  
    

Une chose importante à faire est de tester indépendamment votre logique métier

  

Je ne voudrais certainement pas présumer que la personne qui a écrit le code JAX-RS et qui cherche à tester l’interface de l’interface est en quelque sorte, pour une raison étrange et inexplicable, ignorante de la notion qu’elle peut effectuer des tests unitaires sur d’autres parties de l’appareil. le programme, y compris les classes de logique métier. Il n’est guère utile d’évoquer l’évidence et il a été souligné à maintes reprises que les réponses devaient également être testées.

Jersey et RESTEasy ont tous deux des applications clientes et, dans le cas de RESTEasy, vous pouvez utiliser les mêmes annotations (même en excluant l'interface annotée et en utilisant les côtés client et serveur de vos tests).

REST pas ce que ce service peut faire pour vous; RESTEZ ce que vous pouvez faire pour ce service.

Restez simple. Consultez les https://github.com/valid4j/http-matchers qui peuvent être importés. de Maven Central.

    <dependency>
        <groupId>org.valid4j</groupId>
        <artifactId>http-matchers</artifactId>
        <version>1.0</version>
    </dependency>

Exemple d'utilisation:

// Statically import the library entry point:
import static org.valid4j.matchers.http.HttpResponseMatchers.*;

// Invoke your web service using plain JAX-RS. E.g:
Client client = ClientBuilder.newClient();
Response response = client.target("http://example.org/hello").request("text/plain").get();

// Verify the response
assertThat(response, hasStatus(Status.OK));
assertThat(response, hasHeader("Content-Encoding", equalTo("gzip")));
assertThat(response, hasEntity(equalTo("content")));
// etc...

Si je comprends bien, l’auteur de ce problème a pour objectif principal de découpler la couche JAX RS de la couche 1 de gestion. Et testez uniquement le premier. Nous devons résoudre deux problèmes fondamentaux:

  1. Exécutez un test sur un serveur d'applications / Web, mettez les composants JAX RS il. Et seulement eux.
  2. Faux services commerciaux dans JAX RS couche composants / REST.

Le premier est résolu avec Arquillian. Le second est parfaitement décrit dans arquillican et simulacre

Voici un exemple de code, il peut être différent si vous utilisez un autre serveur d'applications, mais j'espère que vous obtiendrez l'idée de base et les avantages.

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

import com.brandmaker.skinning.service.SomeBean;

/**
* Created by alexandr on 31.07.15.
*/
@Path("/entities")
public class RestBean
{
   @Inject
   SomeBean bean;

   @GET
   public String getEntiry()
   {
       return bean.methodToBeMoked();
   }
}

import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import com.google.common.collect.Sets;

/**
*/
@ApplicationPath("res")
public class JAXRSConfiguration extends Application
{
   @Override
   public Set<Class<?>> getClasses()
   {
       return Sets.newHashSet(RestBean.class);
   }
}


public class SomeBean
{
   public String methodToBeMoked()
   {
       return "Original";
   }
}

import javax.enterprise.inject.Specializes;

import com.brandmaker.skinning.service.SomeBean;

/**
*/
@Specializes
public class SomeBeanMock extends SomeBean
{
   @Override
   public String methodToBeMoked()
   {
       return "Mocked";
   }
}

@RunWith(Arquillian.class)
public class RestBeanTest
{
   @Deployment
   public static WebArchive createDeployment() {
       WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war")
               .addClasses(JAXRSConfiguration.class, RestBean.class, SomeBean.class, SomeBeanMock.class)
               .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
       System.out.println(war.toString(true));
       return war;
   }

   @Test
   public void should_create_greeting() {
       Client client = ClientBuilder.newClient();
       WebTarget target = client.target("http://127.0.0.1:8181/test/res/entities");
       //Building the request i.e a GET request to the RESTful Webservice defined
       //by the URI in the WebTarget instance.
       Invocation invocation = target.request().buildGet();
       //Invoking the request to the RESTful API and capturing the Response.
       Response response = invocation.invoke();
       //As we know that this RESTful Webserivce returns the XML data which can be unmarshalled
       //into the instance of Books by using JAXB.
       Assert.assertEquals("Mocked", response.readEntity(String.class));
   }
}

Quelques notes:

  1. La configuration JAX RS sans web.xml est utilisée ici.
  2. Le client JAX RS est utilisé ici (pas de RESTEasy / Jersey, ils exposent une API plus pratique)
  3. Lorsque le test commence, le coureur d'Arquillian commence à travailler. Ici , vous apprendrez à configurer des tests pour Arquillian avec le serveur d'applications requis.
  4. En fonction du serveur d'application choisi, une URL dans le répertoire test différera un peu. Un autre port peut être utilisé. 8181 est utilisé par Glassfish Embedded dans mon exemple.

J'espère que ça va aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top