我目前正在寻找为 JAX-RS (Java API)创建自动化测试的方法基于RESTful Web Services的Web服务。

我基本上需要一种方法来发送某些输入并验证我得到了预期的响应。我宁愿通过JUnit这样做,但我不确定如何实现。

您使用什么方法测试您的网络服务?

更新:正如entzik指出的那样,将Web服务与业务逻辑分离后,我可以对业务逻辑进行单元测试。但是,我还想测试正确的HTTP状态代码等。

有帮助吗?

解决方案

Jersey 附带了一个出色的RESTful客户端API,使编写单元测试变得非常简单。请参阅Jersey附带的示例中的单元测试。如果您对 Apache Camel 中测试REST支持。 “http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-rest/src/test/java/org/apache/camel/rest/resources/"rel =”noreferrer“>测试用例在这里

其他提示

您可以试用 REST Assured ,这使得非常简单地测试REST服务并验证Java中的响应(使用JUnit或TestNG)。

詹姆斯说;泽西有内置的测试框架。一个简单的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带有一个名为 Jersey测试框架的测试框架,可让您测试RESTful Web服务,包括响应状态代码。您可以使用它在轻量级容器(如Grizzly,HTTPServer和/或EmbeddedGlassFish)上运行测试。此外,该框架可用于在常规Web容器(如GlassFish或Tomcat)上运行测试。

您可能编写了一些实现业务逻辑的Java代码,然后为其生成了Web服务端点。

要做的一件重要事情是独立测试您的业务逻辑。由于它是纯Java代码,因此您可以使用常规JUnit测试来实现。

现在,由于Web服务部分只是一个终点,您要确保生成的管道(存根等)与您的Java代码同步。您可以通过编写调用生成的Web服务Java客户端的JUnit测试来实现。这将在您更改Java签名时通知您,而无需更新Web服务。

如果构建系统在每次构建时自动生成Web服务管道,则可能没有必要测试端点(假设它们都已正确生成)。取决于你的偏执程度。

我使用Apache的 HTTPClient(http://hc.apache.org/) 来呼叫Restful Services 。 HTTP客户端库允许您轻松执行get,post或您需要的任何其他操作。如果您的服务使用JAXB进行xml绑定,则可以创建一个JAXBContext来序列化和反序列化HTTP请求中的输入和输出。

查看 Alchemy rest客户端生成器。这可以使用场景后面的泽西客户端为您的JAX-RS Web服务类生成代理实现。实际上,您将通过单元测试将Web服务方法称为简单的Java方法。处理http身份验证。

如果您需要简单地运行测试以便方便,则不会涉及代码生成。

Disclaimer:我是这个图书馆的作者。

  
    

重要的是要独立测试您的业务逻辑

  

我当然不会认为编写JAX-RS代码并希望对界面进行单元测试的人是出于某种奇怪的,莫名其妙的原因,而忽略了他或她可以对其他部分进行单元测试的概念。该程序,包括业务逻辑类。陈述显而易见的事情几乎没有帮助,并且反复提出要求也需要测试。

Jersey和RESTEasy都有客户端应用程序,在RESTEasy的情况下,您可以使用相同的annoations(甚至可以将带注释的接口分解出来并在测试的客户端和服务器端使用)。

REST不是这项服务可以为您做什么; REST您可以为此服务做些什么。

保持简单。查看可以导入的 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...

据我所知,这个问题的主要目的是将JAX RS层与业务层解耦。而单元测试只是第一个。我们必须解决两个基本问题:

  1. 运行测试一些Web /应用程序服务器,将JAX RS组件放入 它。只有他们。
  2. JAX RS内的模拟业务服务 组件/ REST层。
  3. 第一个是用Arquillian解决的。 第二个在 arquillican and 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 Client(没有RESTEasy / Jersey,它们提供更方便的API)
    3. 测试开始时,Arquillian的跑步者开始工作。 此处您可以找到如何使用所需的应用程序服务器为Arquillian配置测试。
    4. 取决于所选的应用程序服务器,中的URL 测试会略有不同。可以使用另一个端口。 8181是 在我的例子中由Glassfish Embedded使用。
    5. 希望,这会有所帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top