JAX-RS Web Service Unit Testing?

I'm currently looking for ways to create automated tests for the JAX-RS web service (Java API for RESTful Web Services).

I basically need a way to send it to specific inputs and verify that I am getting the expected answers. I would rather do it through JUnit, but I'm not sure how this can be achieved.

What approach do you use to test your web services?

Update: As the encyclist noted, decoupling a web service from business logic allows me to unit test business logic. However, I also want to check the correct HTTP status codes, etc.

+71
java unit-testing junit web-services jax-rs
Sep 23 '08 at 14:18
source share
10 answers

Jersey comes with the excellent RESTful API, which makes unit record tests very easy. See Block Tests for examples that come with Jersey. We use this approach to test REST support in Apache Camel if you're interested here>

+34
Sep 29 '08 at 9:56
source share
— -

You can try out REST Assured , which makes it very easy to test REST services and check the response in Java (using JUnit or TestNG).

+22
Dec 27 '10 at 8:14
source share

As James said; There is a built-in test environment for Jersey. An example of a simple greeting might be:

pom.xml for maven integration. When you run mvn test . Frames launch a grizzly container. You can use a jetty or tomcat through dependency changes.

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

You can check out this sample application.

+10
Feb 25 '15 at 18:10
source share

Although its too late from the date the question was posted, I thought it might be useful to others who have a similar question. Jersey comes with a test platform called the Jersey Test Framework that allows you to test the RESTful web service, including response status codes. You can use it to run tests on light containers, such as Grizzly, HTTPServer and / or EmbeddedGlassFish. In addition, the frame can be used to run your tests on a regular web container such as GlassFish or Tomcat.

+6
Jun 10 '09 at 6:32
source share

You probably wrote some Java code that implements your business logic, and then you created a web services endpoint for it.

An important thing to do is test your business logic yourself. Since this is pure Java code, you can do this with regular JUnit tests.

Now, since part of the web services is just the endpoint, you need to make sure that the created plumbing (stubs, etc.) is synchronized with your java code. you can do this by writing JUnit tests that invoke the created web services Java clients. This will let you know when you change your java signatures without updating the web services stuff.

If your web services system is automatically generated by your build system at each build, then it may not be necessary to check the endpoints (assuming all of this is correctly generated). Depends on your level of paranoia.

+5
Sep 23 '08 at 14:46
source share

I am using Apache HTTPClient (http://hc.apache.org/) to call Restful Services. The HTTP Client library allows you to easily retrieve, publish, or any other operation that you need. If your service uses JAXB to bind xml, you can create a JAXBContext to serialize and deserialize the inputs and outputs from the HTTP request.

+3
Sep 23 '08 at 15:37
source share

Look at the generator of generations of alchemists . This can lead to a proxy implementation for your JAX-RS web service using the jersey client behind the scenes. Effectively, you will call you webservice methods as simple java methods from your unit tests. Also handles HTTP authentication.

No code generation is required if you just need to run tests to make it convenient.

Dislclaimer: I am the author of this library.

+3
May 27 '15 at 11:46
source share

The important thing to do is independently test your business logic.

Of course, I would not assume that the person who wrote the JAX-RS code and is looking for the unit test interface, somehow, for some strange inexplicable reason, does not pay attention to the fact that he or she can test others parts of the program, including business logic classes. It was not good to state the obvious, and it was repeatedly emphasized that the answers should also be verified.

Both Jersey and RESTEasy have client applications, and in the case of RESTEasy you can use the same annotations (even set the annotated interface and use on the client and server side of your tests).

REST is not what this service can do for you; REST what you can do for this service.

+2
Aug 04 '09 at 20:39
source share

Keep it simple. Check out the https://github.com/valid4j/http-matchers , which you can import from Maven Central.

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

Usage example:

 // Statically import the library entry point: import static org.valid4j.matchers.http.HttpResponseMatchers.*; // Invoke your web service using plain JAX-RS. Eg: 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
Jan 28 '16 at 8:33
source share

As I understand it, the main goal of the author of this problem is to disconnect the JAX RS level from the business interface. And unit test is only the first. Here we must solve two main problems:

  • Run the web server / application server in test mode, add the JAX RS components to This. And only they.
  • Manage business services within JAX RS components / REST.

The first is resolved with Arkillian. The second option is beautifully described in arquillican and mock

Here is a sample code, it may differ if you use a different application server, but I hope you get the basic idea and benefits.

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

A few notes:

  • JAX RS configuration without web.xml is used here.
  • The JAX RS client is used here (no RESTEasy / Jersey, they provide a more convenient API)
  • When the test begins, the Arkillian runner begins to work. Here you can find how to configure tests for Arquillian with the necessary application server.
  • Depending on the application server you select, the test URL will be slightly different. Another port may be used. 8181 - used by Glassfish Embedded in my example.

Hope this helps.

+1
Jul 31 '15 at 10:47
source share



All Articles