Модульное тестирование веб-службы JAX-RS? - PullRequest
75 голосов
/ 23 сентября 2008

В настоящее время я ищу способы создания автоматических тестов для веб-службы на основе JAX-RS (Java API для RESTful Web Services).

Мне в основном нужен способ отправить ему определенные входные данные и убедиться, что я получаю ожидаемые ответы. Я бы предпочел сделать это через JUnit, но я не уверен, как этого достичь.

Какой подход вы используете для тестирования своих веб-сервисов?

Обновление: Как указывал entzik, отсоединение веб-службы от бизнес-логики позволяет мне проводить модульное тестирование бизнес-логики. Однако я также хочу проверить правильность кодов состояния HTTP и т. Д.

Ответы [ 10 ]

34 голосов
/ 29 сентября 2008

Джерси поставляется с отличным клиентским API RESTful, который делает написание модульных тестов действительно простым. Смотрите юнит-тесты в примерах, которые поставляются с Джерси. Мы используем этот подход для тестирования поддержки REST в Apache Camel , если вас интересует тестовые примеры здесь

24 голосов
/ 27 декабря 2010

Вы можете попробовать REST Assured , что делает очень простым для тестирования служб REST и проверки ответа в Java (с использованием JUnit или TestNG).

12 голосов
/ 25 февраля 2015

Как сказал Джеймс; Для Джерси есть встроенный тестовый фреймворк . Простой пример «Привет, мир» может быть таким:

pom.xml для интеграции с Maven. Когда вы запускаете mvn test. Каркасы запускают контейнер гризли. Вы можете использовать причал или кота, меняя зависимости.

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

Вы можете проверить это образец приложения.

6 голосов
/ 10 июня 2009

Хотя уже слишком поздно с даты публикации вопроса, подумал, что это может быть полезно для тех, у кого похожий вопрос. Jersey поставляется с тестовой средой, называемой Jersey Test Framework , которая позволяет вам тестировать веб-службу RESTful, включая коды состояния ответа. Вы можете использовать его для запуска тестов на легких контейнерах, таких как Grizzly, HTTPServer и / или EmbeddedGlassFish. Кроме того, инфраструктура может использоваться для запуска ваших тестов на обычном веб-контейнере, таком как GlassFish или Tomcat.

5 голосов
/ 23 сентября 2008

Вы, вероятно, написали некоторый код Java, который реализует вашу бизнес-логику, а затем сгенерировали конечную точку веб-служб для нее.

Важная вещь, которую нужно сделать - это самостоятельно проверить свою бизнес-логику. Поскольку это чистый код Java, вы можете сделать это с помощью обычных тестов JUnit.

Теперь, поскольку часть веб-сервисов - это всего лишь конечная точка, вам нужно убедиться, что сгенерированные сантехника (заглушки и т. Д.) Синхронизированы с вашим Java-кодом. Вы можете сделать это, написав тесты JUnit, которые вызывают сгенерированные Java-клиенты веб-службы. Это позволит вам узнать, когда вы измените свои подписи Java без обновления содержимого веб-служб.

Если ваша система веб-служб автоматически генерируется вашей системой сборки при каждой сборке, то может не потребоваться тестировать конечные точки (при условии, что все они созданы правильно). Зависит от вашего уровня паранойи.

3 голосов
/ 27 мая 2015

Взгляните на Alchemy rest client client . Это может сгенерировать реализацию прокси для вашего класса веб-сервиса JAX-RS, используя клиент-джерси за сценой. По сути, вы будете называть вас методами веб-сервиса как простые java-методы из ваших модульных тестов. Также обрабатывает HTTP-аутентификацию.

Генерация кода не требуется, если вам нужно просто запустить тесты, чтобы это было удобно.

Отказ от ответственности: я являюсь автором этой библиотеки.

3 голосов
/ 23 сентября 2008

Я использую Apache HTTPClient (http://hc.apache.org/) для вызова Restful Services. Библиотека HTTP Client позволяет вам легко выполнять получение, публикацию или любую другую операцию, которая вам нужна. Если ваша служба использует JAXB для привязки xml, вы можете создать JAXBContext для сериализации и десериализации входных и выходных данных из HTTP-запроса.

2 голосов
/ 28 января 2016

Будьте проще. Взгляните на https://github.com/valid4j/http-matchers, который можно импортировать из Maven Central.

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

Пример использования:

// 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...
2 голосов
/ 05 августа 2009

Важным моментом является независимое тестирование вашей бизнес-логики

Я, конечно, не предполагал бы, что человек, который написал код JAX-RS и ищет модульное тестирование интерфейса, каким-то странным, необъяснимым причинам не замечает, что он или она может тестировать другие части Программа, в том числе бизнес-логики. Вряд ли полезно заявлять об очевидном, и неоднократно отмечалось, что ответы также необходимо проверять.

И на Джерси, и на RESTEasy есть клиентские приложения, а в случае с RESTEasy вы можете использовать одни и те же аннотации (даже исключая аннотированный интерфейс и используйте его на стороне клиента и сервера ваших тестов).

ОТДЫХАЙТЕ не то, что эта служба может сделать для вас; ОТДЫХАЙТЕ, что вы можете сделать для этой услуги.

1 голос
/ 31 июля 2015

Как я понимаю, основная цель автора этой проблемы - отделить слой JAX RS от бизнес-уровня. И юнит тест только первый. Здесь необходимо решить две основные проблемы:

  1. Запустите в тесте какой-нибудь веб-сервер / сервер приложений, поместите компоненты JAX RS в Это. И только их.
  2. Ложные бизнес-услуги внутри JAX RS Слой компонентов / REST.

Первый решается с Аркиллианом. Второй прекрасно описан в arquillican и макете

Вот пример кода, он может отличаться, если вы используете другой сервер приложений, но я надеюсь, что вы получите основную идею и преимущества.

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

Пара заметок:

  1. Здесь используется конфигурация JAX RS без web.xml.
  2. Здесь используется JAX RS Client (без RESTEasy / Jersey, они предоставляют более удобный API)
  3. Когда тест начинается, бегун Аркиллиана начинает работать. Здесь вы можете найти, как настроить тесты для Arquillian с необходимым сервером приложений.
  4. В зависимости от выбранного сервера приложений, URL в Тест будет немного отличаться. Можно использовать другой порт. 8181 используется Glassfish Embedded в моем примере.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...