Reputation: 2384
I'm writing unit test for my rest call (implemented in jersey) with the jersey test framework, I'm getting an IncompatibleClassChangeError, and it's really confusing:
Caused by: java.lang.IncompatibleClassChangeError: Class javax.ws.rs.core.Response$Status does not implement the requested interface javax.ws.rs.core.Response$StatusType at com.sun.jersey.spi.container.ContainerResponse.getStatus(ContainerResponse.java:548) at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.commitWrite(ContainerResponse.java:156) at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.write(ContainerResponse.java:133) at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202) at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272) at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276) at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122) at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212) at java.io.BufferedWriter.flush(BufferedWriter.java:236) at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191) at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128) at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88) at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58) at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:299) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1326) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1239) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1229) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:420) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:497) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:684) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at com.sun.grizzly.http.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:188) ... 20 more
My rest call is like this:
@GET
@Produces("application/json")
@Path("/test")
public String test() {
return "it works";
}
My test is like this:
public class MyTest extends JerseyTest {
public MyTest() {
super("com.mypackage");
}
@Test
public void test() throws IllegalArgumentException, IOException {
WebResource webResource = resource();
webResource.path("/test").accept("application/json").get(ClientResponse.class).toString();
}
}
The 2nd line is throwing the exception. So what am I doing wrong here? I'm using jersey 1.4 and also 1.4 for the jersey test framework. Any help would be appreciated. Thanks!
Update: I notice the test will pass if I run it in command line via maven, weird.
Upvotes: 0
Views: 4672
Reputation: 8990
Try to change the setup of your Jersey Test to override configure instead:
public class MyTest extends JerseyTest {
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
MyResource service = new MyResource();
ResourceConfig config = new ResourceConfig();
config.register(service);
Map<String, Object> mapProps = new HashMap<>(); mapProps.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE,Boolean.TRUE);
config.addProperties(mapProps);
return config;
}
/**
* expects HTTP 200 for valid request
* @param l
* @param expectedText
*/
private void expectValidRequest(String expectedText) {
Response output = target("/test").request(MediaType.APPLICATION_JSON).get();
Assert.assertTrue(output.getStatus() == HttpStatus.OK_200);
Assert.assertTrue(output.getHeaders().get("Content-Type").get(0).equals(MediaType.APPLICATION_JSON));
String textBody = output.readEntity(String.class);
Assert.assertTrue(textBody.equals(expectedText));
}
@Test
public void test() throws IllegalArgumentException, IOException {
String expectedText = "{\"name\": \"it works\"}";
expectValidRequest(l, expectedText);
}
}
// your Client response class - sample
class ClientResponse {
public ClientResponse(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// your web service
@GET
@Produces("application/json")
@Path("/test")
public ClientResponse test() {
return new ClientResponse("it works");
}
Upvotes: 0
Reputation: 2242
your method returns a string
@GET
@Produces("application/json")
@Path("/test")
public String test() {
return "it works";
}
so you should be expecting a String.class
public class MyTest extends JerseyTest {
public MyTest() {
super("com.mypackage");
}
@Test
public void test() throws IllegalArgumentException, IOException {
WebResource webResource = resource();
assertEquals("it works",webResource.path("/test").accept("application/json").get(String.class));
}
}
Upvotes: 0
Reputation: 2345
Not really an answer to your question, but I have to ask it anyway. I'm sure you've simplified the example, but I don't really see much value in writing a unit test for this. It seems as if you're testing the framework more than any real application logic. If your get request invokes some rules to return some sort of model objects, simply wrap that code in an object and use DI to inject it.
For example:
@GET @Produces("application/json") @Path("/movies") public List<Movie> catalog() { return this.rentalManager.findAll(); }
Now you can just use a boring old JUnit test and not deal with any of the framework issues. Is it testing that the proper annotations are present on your class? Not really, but I suspect that it's something that will be caught in acceptance testing and doesn't change much once it's coded.
Of course if it really bothered you then you could certainly write some kind of test like:
@Test public void catalogSupportsGetRequests() { verifyMethodHasAnnotation(MyResource.class, "catalog", "GET"); } @Test public void catalogProducesJson() { verifyMethodHasAnnotation(MyResource.class, "catalog", "Produces", "application/json"); } // You get the idea.
Hope that helps! Brandon
Upvotes: 0