2010-12-18 162 views
0

我在写单元测试我的REST调用(泽西实现)与球衣测试框架,我发现了一个IncompatibleClassChangeError,这真的令人困惑:单元测试球衣REST调用与球衣测试框架

 
    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 

我的REST调用是这样的:

@GET 
@Produces("application/json") 
@Path("/test") 
public String test() { 
    return "it works"; 
} 

我的测试是这样的:

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

的2 nd行抛出异常。那么我在这里做错了什么?我使用球衣1.4和球衣测试框架1.4。任何帮助,将不胜感激。谢谢!

更新:我注意到测试通过,如果我通过maven命令行运行它,很奇怪。

+0

我似乎遇到了这个异常后,添加一个Servlet过滤器到我的应用程序n(通过org.springframework.web.filter.DelegatingFilterProxy),过滤器将Headers添加到HttpServletResponse。 – xgMz 2011-06-16 22:21:28

回答

0

不是真的回答你的问题,但我必须反问。我相信你已经简化了这个例子,但是我并没有看到写这个单元测试的很多价值。看起来好像您正在测试框架比任何实际的应用程序逻辑更多。如果您的get请求调用某些规则返回某种模型对象,只需将该代码包装在一个对象中,然后使用DI注入它。

例如:

 
@GET 
@Produces("application/json") 
@Path("/movies") 
public List<Movie> catalog() { 
    return this.rentalManager.findAll(); 
} 

现在你可以只使用一个无聊的老JUnit测试,不与任何框架问题处理。它是否测试了班级中正确的注释?并非如此,但我怀疑它会在验收测试中被捕获,并且一旦编码就不会发生太大变化。

当然,如果真的打扰你,那么你当然可以写一些类型的测试,如:

 
@Test 
public void catalogSupportsGetRequests() { 
    verifyMethodHasAnnotation(MyResource.class, "catalog", "GET"); 
} 

@Test 
public void catalogProducesJson() { 
    verifyMethodHasAnnotation(MyResource.class, "catalog", "Produces", "application/json"); 
} 

// You get the idea. 

希望帮助! 布兰登

0

你的方法返回一个字符串

@GET 
@Produces("application/json") 
@Path("/test") 
public String test() { 
    return "it works"; 
} 

所以你应该期待一个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)); 
    } 
} 
0

试图改变自己的球衣测试的设置覆盖配置,而不是:

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