JAX-RS 웹 서비스 테스트?


84

현재 JAX-RS (RESTful 웹 서비스 용 Java API) 기반 웹 서비스에 대한 자동화 된 테스트를 만드는 방법을 찾고 있습니다 .

기본적으로 특정 입력을 보내고 예상 응답을 받는지 확인하는 방법이 필요합니다. JUnit을 통해이 작업을 수행하고 싶지만 어떻게 달성 할 수 있는지 잘 모르겠습니다.

웹 서비스를 테스트하기 위해 어떤 접근 방식을 사용합니까?

업데이트 : entzik이 지적했듯이 비즈니스 로직에서 웹 서비스를 분리하면 비즈니스 로직을 단위 테스트 할 수 있습니다. 그러나 올바른 HTTP 상태 코드 등을 테스트하고 싶습니다.


6
좋은 질문입니다. 그러나 HTTP를 통해 테스트하는 경우 이것이 통합 테스트라는 것을 알 수 있습니다.
Tom Duckering 2011 년

톰. 당신은 절대적으로 옳다. 이를 위해 더미 HTTP 에뮬레이터 / 경량 컨테이너를 삽입해야합니다. node.js에서 world supertest는 이것을 만듭니다. express.js를 에뮬레이션 할 수 있습니다.
Fırat KÜÇÜK

답변:


34

Jersey 는 단위 테스트 작성을 정말 쉽게 해주는 훌륭한 RESTful 클라이언트 API와 함께 제공됩니다. Jersey와 함께 제공되는 예제에서 단위 테스트를 참조하십시오. 이 접근 방식을 사용하여 Apache Camel 에서 REST 지원을 테스트합니다. 관심이있는 경우 테스트 사례는 여기에 있습니다.


6
re : now bad link 기본적으로 jersey의 소비자를 사용하여 웹 리소스를 사용함으로써 단위 테스트를 보여주는 jersey / samples에 언급 된 예제를 찾을 수 있습니다. download.java.net/maven/2/com/sun/jersey/samples/bookstore/…
rogerdpack 2009

2
이 프로젝트는 GitHub에 있습니다. src / test 폴더에서 테스트를 찾으십시오. github.com/jersey/jersey/tree/master/examples/bookstore-webapp
Venkat

2
나는이 대답을 의심하지 않는다. 그러나 Jersey가 항상 JAX-RS 대화에 들어가는 것이 엄청나게 웃기다. 어떤 경우에는 (불행히도 정확히 말하자면 WebSphere) 사용할 수없고 모든 수용 가능한 대답의 99 %를 렌더링한다. 스택 오버플로에서 null 및 void.

26

REST Assured 를 사용해 볼 수 있습니다. REST 서비스를 테스트하고 Java에서 응답을 검증하는 것이 매우 간단합니다 (JUnit 또는 TestNG 사용).


1
... 나는 도서관 보았다 좋은 원인 게시물을 선정,하지만 그들은 확실히 의존 항아리를 많이 사용
페리 튜에게

17

James가 말했듯이; 기본 제공 테스트 프레임 워크가 있습니다.Jersey에 대한 가 있습니다. 간단한 hello world 예제는 다음과 같습니다.

maven 통합을위한 pom.xml. 당신은 실행하면 mvn test. 프레임 워크는 그리즐리 컨테이너를 시작합니다. 종속성 변경을 통해 jetty 또는 tomcat을 사용할 수 있습니다.

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

샘플 애플리케이션을 확인할 수 있습니다 .


Jersey 2.29.1에서는 찾을 수 없음 오류가 발생 jersey-hk2했기 때문에 종속성 으로 추가해야했습니다 java.lang.IllegalStateException: InjectionManagerFactory( 이 질문 참조 ). 그렇지 않으면이 예제가 잘 작동합니다.
Sarah N

7

비즈니스 로직을 구현하는 자바 코드를 작성한 다음이를위한 웹 서비스 엔드 포인트를 생성했을 것입니다.

중요한 것은 비즈니스 로직을 독립적으로 테스트하는 것입니다. 순수한 자바 코드이기 때문에 일반 JUnit 테스트로 할 수 있습니다.

이제 웹 서비스 부분은 끝 점일 뿐이므로 생성 된 배관 (스텁 등)이 Java 코드와 동기화되어 있는지 확인해야합니다. 생성 된 웹 서비스 자바 클라이언트를 호출하는 JUnit 테스트를 작성하면됩니다. 이것은 웹 서비스 항목을 업데이트하지 않고 Java 서명을 변경할 때 알려줍니다.

웹 서비스 배관이 모든 빌드에서 빌드 시스템에 의해 자동으로 생성되는 경우 엔드 포인트를 테스트 할 필요가 없습니다 (모두 올바르게 생성되었다고 가정). 편집증 수준에 따라 다릅니다.


2
반환되는 실제 HTTP 응답, 특히 HTTP 상태 코드도 테스트해야하지만 당신 말이 맞습니다.
Einar

6

질문을 게시 한 날짜로부터 너무 늦었지만 비슷한 질문을 가진 다른 사람들에게 유용 할 것이라고 생각했습니다. Jersey에는 응답 상태 코드를 포함하여 RESTful 웹 서비스를 테스트 할 수 있는 Jersey Test Framework 라는 테스트 프레임 워크가 제공됩니다 . 이를 사용하여 Grizzly, HTTPServer 및 / 또는 EmbeddedGlassFish와 같은 경량 컨테이너에서 테스트를 실행할 수 있습니다. 또한 프레임 워크를 사용하여 GlassFish 또는 Tomcat과 같은 일반 웹 컨테이너에서 테스트를 실행할 수 있습니다.


호출 핸들러를 모의하는 방법에 대한 좋은 예가 있습니까? JerseyHttpCall-> MyResource-> CallHandler.getSomething () 여기서 CallHandler를 어떻게 모의 할 수 있습니까?
Balaji Boggaram Ramanarayan 2014

3

Apache의 HTTPClient (http://hc.apache.org/) 를 사용하여 Restful Services를 호출합니다. HTTP 클라이언트 라이브러리를 사용하면 가져 오기, 게시 또는 필요한 기타 작업을 쉽게 수행 할 수 있습니다. 서비스에서 xml 바인딩에 JAXB를 사용하는 경우 JAXBContext를 만들어 HTTP 요청의 입력 및 출력을 직렬화 및 역 직렬화 할 수 있습니다.


3

Alchemy Rest 클라이언트 생성기 살펴보기 . 이렇게하면 뒤에서 저지 클라이언트를 사용하여 JAX-RS 웹 서비스 클래스에 대한 프록시 구현을 생성 할 수 있습니다. 효과적으로 단위 테스트에서 웹 서비스 메서드를 간단한 Java 메서드로 호출합니다. http 인증도 처리합니다.

간단하게 테스트를 실행해야하는 경우 코드 생성이 필요하지 않으므로 편리합니다.

면책 조항 : 나는이 라이브러리의 저자입니다.


2

단순하게 유지하십시오. Maven Central에서 가져올 수있는 https://github.com/valid4j/http-matchers 를 살펴보세요 .

    <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...

1

중요한 것은 비즈니스 로직을 독립적으로 테스트하는 것입니다.

JAX-RS 코드를 작성하고 인터페이스를 단위 테스트하려는 사람이 기이하고 설명 할 수없는 이유로 프로그램의 다른 부분을 단위 테스트 할 수 있다는 개념을 모르는 사람이라고 생각하지 않습니다. 비즈니스 로직 클래스를 포함합니다. 명백한 것을 언급하는 것은 거의 도움이되지 않으며 응답도 테스트 할 필요가 있다는 점이 반복적으로 제기되었습니다.

Jersey와 RESTEasy 모두 클라이언트 응용 프로그램이 있으며 RESTEasy의 경우 동일한 주석을 사용할 수 있습니다 (주석이있는 인터페이스를 제외하고 테스트의 클라이언트 및 서버 측에서 사용).

REST는이 서비스가 당신을 위해 할 수있는 일이 아닙니다. 이 서비스에 대해 수행 할 수있는 작업을 REST하십시오.


사람들은 교차 절단 문제를 테스트하고 싶을 수 있습니다. 예를 들어 유효성 검사, 인증, 원하는 HTTP 헤더 등이 있습니다. 따라서 사람들은 JAX-RS 코드 테스트를 선호 할 수 있습니다.
Fırat KÜÇÜK

내 응용 프로그램에서 ModelMapper를 사용하여 "DTO"클래스에서 기본 "서비스"클래스에서 이해하는 "비즈니스 개체"클래스로 "매핑"합니다. 이것은 독립적으로 테스트하는 것이 좋은 예입니다.
jkerak

그리고 때로는 REST 애플릿의 복잡성이 너무 적어서 현재의 경우와 같이 모의가 애플리케이션 계층보다 클 수 있습니다. :)
tekHedd

1

이 문제의 인증 자의 주요 목적은 비즈니스 1에서 JAX RS 계층을 분리하는 것입니다. 그리고 첫 번째 만 단위 테스트합니다. 여기서 해결해야 할 두 가지 기본 문제 :

  1. 일부 웹 / 애플리케이션 서버를 테스트에서 실행하고 JAX RS 구성 요소를 그 안에 넣습니다. 그리고 그들 만.
  2. JAX RS 구성 요소 / REST 계층 내에서 비즈니스 서비스를 모의합니다.

첫 번째 문제는 Arquillian로 해결됩니다. 두 번째는 arquillican 및 mock으로

다음은 코드의 예입니다. 다른 애플리케이션 서버를 사용하면 다를 수 있지만 기본적인 아이디어와 이점을 얻으시기 바랍니다.

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. web.xml이없는 JAX RS 구성이 여기에 사용됩니다.
  2. 여기에서는 JAX RS 클라이언트가 사용됩니다 (RESTEasy / Jersey가 없으며보다 편리한 API를 제공함).
  3. 테스트가 시작되면 Arquillian의 주자가 작동하기 시작합니다. 여기 에서 필요한 애플리케이션 서버로 Arquillian 테스트를 구성하는 방법을 찾을 수 있습니다.
  4. 선택한 응용 프로그램 서버에 따라 테스트의 URL이 약간 다릅니다. 다른 포트를 사용할 수 있습니다. 8181은 내 예제에서 Glassfish Embedded에서 사용됩니다.

희망, 도움이 될 것입니다.


내장 저지 테스트 프레임 워크에서 이러한 유형을 지원합니까? Jersey에서 이미 사용할 수있는 것이 있다면 "아직 다른 프레임 워크"와 모든 병을 프로젝트에 추가하는 것을 주저합니다.
jkerak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.