Hier ist ein Beispiel für eine Ressourcenklasse:
@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;
}
}
Und der JerseyTest für die Ressource:
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.
}
}
Ich kann Trikottests für alle anderen Ressourcen ausführen, mit Ausnahme derer, die @Context HttpServletRequest
als Eingabeparameter verwenden. Es gibt einen InternalServerErrorException: HTTP 500 Internal Server Error.
Es folgt der Stacktrace:
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)
Ihre Ausnahme hängt mit der Tatsache zusammen, dass die HttpServletRequest
null
ist.
Jersey Dokumentation sagt:
3.6. Verwendung von @Context
In früheren Abschnitten wurde die Verwendung von @Context eingeführt. In Kapitel 5 der JAX-RS-Spezifikation sind alle Standard-JAX-RS-Java-Typen aufgeführt, die mit @Context verwendet werden können.
Wenn Sie eine JAX-RS -Anwendung mit servletthen ServletConfig implementieren, stehen ServletContext, HttpServletRequest und HttpServletResponse mit @Context zur Verfügung.
Ich vermute, dass Sie jersey-test-framework-provider-grizzly2
verwenden, der es nicht unterstützt.
Wenn Sie Zugriff auf HttpServletResponse
haben möchten, entfernen Sie diese Abhängigkeit und fügen Sie Folgendes hinzu:
<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>
Jetzt möchten Sie JerseyTest eigentlich anweisen, den richtigen Testserver zu starten. Dazu müssen Sie eine Methode protected TestContainerFactory getTestContainerFactory()
überschreiben. Bitte achten Sie darauf, <your-Java-package>
durch den tatsächlichen Namen Ihres Pakets zu ersetzen .
@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();
}
};
}
};
}
Sie können auch org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory
für eine bessere Implementierung der Fabrik überprüfen.
Sie können auch ein verspottetes HttpServletRequest-Objekt in die configure-Methode einfügen. Hier ist ein Beispiel für Jersey 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) {});
}
}
Jersey 2:
final HttpServletRequest request = mock(HttpServletRequest.class);
resourceConfig.register(new AbstractBinder() {
@Override
protected void configure() {
bind(request).to(HttpServletRequest.class);
}
});
Also endlich bekomme ich eine funktionierende Lösung (Es kommt der populärsten Antwort nahe, aber mit kleinen Änderungen):
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>
Fügen Sie der Anwendung die folgende abstrakte Klasse hinzu:
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();
}
};
}
};
}
}
Und um Rest zu testen, musst du folgendes tun:
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());
}
}
Siehe auch peeskillets Antworten auf diesen Stapelüberlauf-Thread:[link]
(Keine der derzeit aufgelisteten Lösungen hat für mich funktioniert)
Dieses Problem scheint schon lange da zu sein. Zur Erklärung von @ lpiepiora benötigen wir einen Servlet-basierten Testcontainer. Und es gibt bereits eine in jersey-test-framework-provider-grizzly2
(weiß nicht, ob es diese gibt, wenn die Frage gepostet wird), die GrizzlyWebTestContainerFactory
ist und eine andere DeploymentContext
erfordert. Ziehen Sie den neuesten Git und Sie finden ein Beispiel in test-framework/providers/grizzly2/src/test/Java/org/glassfish/jersey/test/grizzly/web/GrizzlyWebTest.Java
. Um klar und einfach zu sein, müssen Sie in Ihrer Basistestklasse nur die folgenden Überschreibungen hinzufügen:
// --- 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...
(Ersetzen Sie YourResourceConfig
durch Ihre echte.)
BEARBEITEN: Wenn Sie Jersey mit jersey-spring3
verwenden, schlägt die oben beschriebene Lösung fehl, da all Ihre Spring Beans fehlen. Etwas reparieren:
@Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext
.servlet(new ServletContainer(new YourResourceConfig()))
.addListener(ContextLoaderListener.class)
.contextParam("contextConfigLocation", "classpath:applicationContext.xml")
.build();
}