使用球衣测试框架进行单元测试球衣休息呼叫

发布于 2024-10-07 21:57:33 字数 2846 浏览 0 评论 0原文

我正在使用泽西岛测试框架为我的休息调用(在泽西岛中实现)编写单元测试,我收到一个 IncompleteClassChangeError ,这真的很令人困惑:

    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

我的休息调用是这样的:

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

第二行是抛出异常。那么我在这里做错了什么?我使用 jersey 1.4 以及 1.4 作为 jersey 测试框架。任何帮助将不胜感激。谢谢!

更新:我注意到如果我通过 Maven 在命令行中运行测试就会通过,很奇怪。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼眸 2024-10-14 21:57:33

虽然不是你问题的答案,但我还是不得不问。我确信您已经简化了这个示例,但我并没有真正看到为此编写单元测试有多大价值。看起来您对框架的测试似乎比对任何实际应用程序逻辑的测试还要多。如果您的 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.

希望有帮助!
布兰登

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

胡大本事 2024-10-14 21:57:33

你的方法返回一个字符串

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

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));
    }
}
情话难免假 2024-10-14 21:57:33

尝试更改 Jersey Test 的设置以覆盖配置:

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

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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文