21

这是一个示例资源类:

@Path("/resource") 
public class SomeResource { 
    @GET 
    @Produces({MediaType.APPLICATION_XML}) 
    public String someMethod(@QueryParam("param1") String param1, ..., @Context HttpServletRequest request) { 
            String remoteUser = request.getRemoteAddr(); 
            // Business logic here. 
            return response; 
    } 
} 

以及资源的 JerseyTest:

public class TestSomeResource extends JerseyTest    { 
    @Override 
    protected Application configure() { 
            enable(TestProperties.LOG_TRAFFIC); 
            return new ResourceConfig(SomeResource.class); 
    } 

    @Test 
    public void testXMLResponse()   { 
            String response = target("resource") 
                            .queryParam("param1", param1) 
                            // More parameters here. 
                            .request() 
                            .accept(MediaType.APPLICATION_XML) 
                            .get(String.class); 
            // Some assertions on response. 
    } 
} 

@Context HttpServletRequest除了用作输入参数的资源之外,我能够对所有其他资源运行球衣测试。它给出了一个InternalServerErrorException: HTTP 500 Internal Server Error.

以下是堆栈跟踪:

javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error 
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:904) 
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:749) 
    at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:88) 
    at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:650) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:421) 
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:646) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:375) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:275) 
    at com.mysample.TestSomeResource.testXMLResponse(TestSomeResource.java:15) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
4

7 回答 7

23

HttpServletRequest您的异常与is的事实有关null

泽西岛文件说:

3.6. @Context 的使用

前面的部分已经介绍了@Context 的使用。JAX-RS 规范的第 5 章介绍了可以与 @Context 一起使用的所有标准 JAX-RS Java 类型。

当使用 servlet 部署 JAX-RS应用程序时,可以使用 @Context 使用 ServletConfig、ServletContext、HttpServletRequest 和 HttpServletResponse。

我猜你使用jersey-test-framework-provider-grizzly2的是不支持它的。

如果您想有权HttpServletResponse删除该依赖项并添加:

<dependency>
    <groupId>org.glassfish.jersey.test-framework</groupId>
    <artifactId>jersey-test-framework-core</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-servlet</artifactId>
    <version>2.1</version>
</dependency>

现在您实际上想告诉 JerseyTest 启动正确的测试服务器,为此您必须覆盖一个方法protected TestContainerFactory getTestContainerFactory()请务必替换<your-java-package>为您的包裹的实际名称

@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
    return new TestContainerFactory() {
        @Override
        public TestContainer create(final URI baseUri, final ApplicationHandler application) throws IllegalArgumentException {
            return new TestContainer() {
                private HttpServer server;

                @Override
                public ClientConfig getClientConfig() {
                    return null;
                }

                @Override
                public URI getBaseUri() {
                    return baseUri;
                }

                @Override
                public void start() {
                    try {
                        this.server = GrizzlyWebContainerFactory.create(
                                baseUri, Collections.singletonMap("jersey.config.server.provider.packages", "<your-java-package>")
                        );
                    } catch (ProcessingException e) {
                        throw new TestContainerException(e);
                    } catch (IOException e) {
                        throw new TestContainerException(e);
                    }
                }

                @Override
                public void stop() {
                    this.server.stop();
                }
            };

        }
    };
}

您还可以检查org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory工厂的更好实施。

于 2013-08-01T08:47:58.900 回答
13

您还可以在 configure 方法中注入一个模拟的 HttpServletRequest 对象。这是泽西岛 1 的示例:

public abstract class AbstractIntegrationTest extends AbstractJerseyTest {

    protected HttpServletRequest httpServletRequest;

    @Override
    protected void configure(final ResourceConfig config) throws Exception {
        // create a mock and inject it via singleton provider
        httpServletRequest = mock(HttpServletRequest.class);
        config.getSingletons().add(
                new SingletonTypeInjectableProvider<Context, HttpServletRequest>(
                        HttpServletRequest.class, httpServletRequest) {});
    }

}

球衣 2:

final HttpServletRequest request = mock(HttpServletRequest.class);
resourceConfig.register(new AbstractBinder() {
                            @Override
                            protected void configure() {
                                bind(request).to(HttpServletRequest.class);
                            }
                        });
于 2014-10-28T13:14:16.720 回答
1

所以最后我得到了可行的解决方案(它接近最流行的答案,但变化很小):


pom.xml

<properties>    
  <jersey.version>2.22.1</jersey.version>
</properties>

    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-inmemory</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-servlet</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>

将以下抽象类添加到应用程序:

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.grizzly2.servlet.GrizzlyWebContainerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.spi.TestContainer;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;

import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.Application;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;

public abstract class RestTest extends JerseyTest {

    @Override
    protected Application configure() {
        enable(TestProperties.LOG_TRAFFIC);
        return new ResourceConfig();
    }

    abstract protected String getRestClassName();

    @Override
    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
        return new TestContainerFactory() {
            @Override
            public TestContainer create(URI baseUri, DeploymentContext deploymentContext) {
                return new TestContainer() {
                    private HttpServer server;

                    @Override
                    public ClientConfig getClientConfig() {
                        return null;
                    }

                    @Override
                    public URI getBaseUri() {
                        return baseUri;
                    }

                    @Override
                    public void start() {
                        try {
                            this.server = GrizzlyWebContainerFactory.create(
                                    baseUri, Collections.singletonMap(ServerProperties.PROVIDER_CLASSNAMES, getRestClassName())
                            );
                        } catch (ProcessingException | IOException e) {
                            throw new TestContainerException(e);
                        }
                    }

                    @Override
                    public void stop() {
                        this.server.shutdownNow();

                    }
                };
            }
        };
    }

}

要测试 Rest 你需要这样做:

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;

import static org.junit.Assert.assertEquals;

public class YourRestTest extends RestTest {

    private static final Logger LOG = LoggerFactory.getLogger("TestLog");

    @Override
    protected String getRestClassName() {
        return "com.app.rest.YourRest";
    }


    @Test
    public void test() throws URISyntaxException, IOException {
        String ttt = new String(Files.readAllBytes(Paths.get(YourRestTest.class.getResource("/rest_resource/ttt.json").toURI())));
        Response response = target("/xxx").path("/yyyy").request().post(Entity.entity(ttt, "application/json"));
        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
    }
}
于 2015-12-17T08:55:37.197 回答
0

好像这个问题很久以前就存在了。正如@lpiepiora 的解释,我们需要一个基于 Servlet 的测试容器。并且已经有一个jersey-test-framework-provider-grizzly2不知道问题发布时是否有),即GrizzlyWebTestContainerFactory,它需要一个不同的DeploymentContext。拉取最新的 git,你会在test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/GrizzlyWebTest.java. 为了简单明了,您只需要在基本测试类中添加这些覆盖:

// --- For Servlet-based test container --- begins ---

@Override
protected DeploymentContext configureDeployment() {
    return ServletDeploymentContext.forServlet(new ServletContainer(new YourResourceConfig())).build();
}

@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
    return new GrizzlyWebTestContainerFactory();
}

// --- For Servlet-based test container --- ends ---

// other stuff...

YourResourceConfig(用你的真实替换。)

编辑: 如果您将 Jersey 与 一起使用jersey-spring3,您会发现上述解决方案由于缺少所有 Spring bean 而失败。要解决这个问题:

@Override
protected DeploymentContext configureDeployment() {
    return ServletDeploymentContext
            .servlet(new ServletContainer(new YourResourceConfig()))
            .addListener(ContextLoaderListener.class)
            .contextParam("contextConfigLocation", "classpath:applicationContext.xml")
            .build();
}
于 2016-08-15T02:37:31.097 回答
0

我有一个类似的问题,并通过一个测试容器工厂解决了它。

public class SessionRestTest extends JerseyTest {

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        // standard servername and port is localhost:9998
        return new GrizzlyWebTestContainerFactory();
    }

    @Override
    protected DeploymentContext configureDeployment() {
        ResourceConfig config = new ResourceConfig(SessionRest.class);
        return ServletDeploymentContext.forServlet(
                new ServletContainer(config)).build();
    }

    private Response get() {
        return target("/session/logout").request().get();
    }

    @Test
    public void testRedirectURL() {
        Response response = get();
        assertEquals("should return status 200", HttpStatus.OK_200, response.getStatus());
    }

}
于 2021-07-26T13:12:23.260 回答
0

另请参阅此 stackoverflow 线程上peeskillet 的答案: [链接]

(目前列出的解决方案都不适合我)

于 2016-07-21T17:20:41.550 回答
-1

更简单的方法是在测试构造函数中提供正确的工厂:

TestSomeResource() {
    super(new GrizzlyWebTestContainerFactory());
}

并提供 servlet 上下文:

@Override
protected DeploymentContext configureDeployment() {
    return ServletDeploymentContext.forPackages("...").build(); // or other builder method
}
于 2016-01-29T13:51:35.457 回答