Я настроил RESTassured
для работы с undertow
с моим приложением REST в памяти, используя maven, который использует фазы pre-integration-test
и post-integration-test
, чтобы установить его как демон и разорвать его.
Мой большой недостаток в том, что undertow выплевывает следы стека в конце фаз интеграционного теста, как будто RESTassured никогда не освобождает свои HTTP-соединения.
Итак, мой вопрос:
Что мне нужно сделать, чтобы правильно закрывать HTTP-соединения после каждого теста, в Undertow или в RESTassured?
Вот кровавые подробности.
Сервер Undertow
Я запускаю Undertow со стандартным кодом Undertow, который можно найти по всему SO:
HttpHandler contextHandler = Handlers.path()
.addPrefixPath("/", manager.start());
return Undertow.builder()
.addHttpListener(port, address,
new GracefulShutdownHandler(contextHandler))
.build();
Stacktraces
Существует один для каждого вызова REST, который выполняет RESTassured. Они выглядят так:
19:07:07.569 io : Error reading request : DEBUG : XNIO-1 I/O-1 :
io.undertow.server.protocol.http.HttpReadListener
java.io.IOException:
An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:158)
[snipped - see below for full stacktraces]
RESTassured
Вот как выглядит каждый блок тестового кода:
@Test
public void test() {
RequestSpecification requestSpecification =
new RequestSpecBuilder()
.setContentType(ContentType.JSON)
.addFilter(new ResponseLoggingFilter())
.addFilter(new RequestLoggingFilter())
.build();
given().spec(requestSpecification)
.queryParam("name", "honky")
.queryParam("description", "oh my")
.queryParam("actualizationDate", "1999-12-31T23:59:59Z")
.queryParam("active", "True")
.when()
.post("2/widget/save")
.then()
.statusCode(200);
Журналы
А вот журналы ниже.
Уровень ведения журнала откатов установлен на TRACE
- Я бы хотел, чтобы они выводили немного больше. Все еще освежает, хотя по сравнению с Bloatosaurus spring.io :)
Если вы оказались отвлечены двумя вызовами, зарегистрированными с помощью undertow.HttpServerExchange
в блоке предварительного тестирования, они будут в порядке. Это:
- вызов, чтобы узнать, работает ли сервер (не уверен)
- вызов покоя для создания тестового пользователя (также не уверен)
В случае, если кто-то думает, что проблема с ними, я проверил запуск и останов без промежуточных тестов, и нет никаких исключений IOException, поэтому я не думаю, что они вызывают проблему.
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:java (pre-int-test) @ gem-widget ---
13:49:55.951 request : UT015007: Stack trace on error enabled for deployment integration-testing, please do not enable for production use : WARN : Thread-2 : io.undertow.servlet.core.DeploymentManagerImpl
13:49:55.996 session : Setting default session timeout to 1800 : DEBUG : Thread-2 : org.jboss.logging.DelegatingBasicLogger
13:49:56.026 servlet : 1 Spring WebApplicationInitializers detected on classpath : INFO : Thread-2 : io.undertow.servlet.spec.ServletContextImpl
13:49:56.101 session : Registered session listener io.undertow.servlet.core.SessionListenerBridge@48b96dfa : DEBUG : Thread-2 : io.undertow.server.session.InMemorySessionManager
13:49:56.105 servlet : Initializing Spring root WebApplicationContext : INFO : Thread-2 : io.undertow.servlet.spec.ServletContextImpl
13:50:13.112 servlet : Initializing Spring FrameworkServlet 'dispatcher' : INFO : Thread-2 : io.undertow.servlet.spec.ServletContextImpl
13:50:13.226 undertow : starting undertow server io.undertow.Undertow@5eb8dc7d : DEBUG : Thread-2 : io.undertow.Undertow
13:50:14.378 undertow : Configuring listener with protocol HTTP for interface localhost and port 8080 : DEBUG : Thread-2 : io.undertow.Undertow
13:50:14.424 undertow : Configuring listener with protocol HTTP for interface 0.0.0.0 and port 8090 : DEBUG : Thread-2 : io.undertow.Undertow
13:50:14.877 request : Opened connection with /127.0.0.1:58156 : TRACE : XNIO-1 I/O-1 : io.undertow.server.protocol.http.HttpOpenListener
13:50:15.070 HttpServerExchange : Starting to write response for HttpServerExchange{ GET / request {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], Connection=[keep-alive], Content-Type=[application/json], User-Agent=[Java/1.8.0_131], Host=[localhost:8080]} response {Connection=[keep-alive], Content-Type=[application/json;charset=ISO-8859-1], Content-Length=[0], Date=[Wed, 07 Nov 2018 13:50:15 GMT]}} : TRACE : XNIO-1 task-1 : io.undertow.server.HttpServerExchange
13:50:15.387 HttpServerExchange : Starting to write response for HttpServerExchange{ POST /2/mgmt/create_user/TEST/true request {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], Connection=[keep-alive], Content-Type=[application/json], User-Agent=[Java/1.8.0_131], Host=[localhost:8080]} response {Connection=[keep-alive], Content-Length=[0], Date=[Wed, 07 Nov 2018 13:50:15 GMT]}} : TRACE : XNIO-1 task-2 : io.undertow.server.HttpServerExchange
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.1:integration-test (default) @ gem-widget ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.megacorp.widget.rest.WidgetSaveTests
13:50:19.928 request : Opened connection with /127.0.0.1:58170 : TRACE : XNIO-1 I/O-3 : io.undertow.server.protocol.http.HttpOpenListener
13:50:19.935 HttpServerExchange : Starting to write response for HttpServerExchange{ GET / request {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], Connection=[keep-alive], Content-Type=[application/json], User-Agent=[Java/1.8.0_131], Host=[localhost:8080]} response {Connection=[keep-alive], Content-Type=[application/json;charset=ISO-8859-1], Content-Length=[0], Date=[Wed, 07 Nov 2018 13:50:19 GMT]}} : TRACE : XNIO-1 task-3 : io.undertow.server.HttpServerExchange
Request method: POST
Request URI: http://localhost:8080/2/widget/save?name=THARG.YES.GOOD.IDEA.6.7.8.9&description=oh%20my&actualizationDate=1999-12-31T23%3A59%3A59Z&active=True
Proxy: <none>
Request params: <none>
Query params: name=THARG.YES.GOOD.IDEA.6.7.8.9
description=oh my
actualizationDate=1999-12-31T23:59:59Z
active=True
Form params: <none>
Path params: <none>
Headers: Accept=*/*
Content-Type=application/json; charset=UTF-8
Cookies: <none>
Multiparts: <none>
Body: <none>
13:50:22.996 request : Opened connection with /127.0.0.1:58171 : TRACE : XNIO-1 I/O-4 : io.undertow.server.protocol.http.HttpOpenListener
13:50:23.031 transfer-encoding : No content, starting next request : TRACE : XNIO-1 I/O-4 : io.undertow.server.protocol.http.HttpTransferEncoding
13:50:23.276 HttpServerExchange : Starting to write response for HttpServerExchange{ POST /2/widget/save request {Accept=[*/*], Connection=[Keep-Alive], Accept-Encoding=[gzip,deflate], Content-Type=[application/json; charset=UTF-8], Content-Length=[0], User-Agent=[Apache-HttpClient/4.5.3 (Java/1.8.0_131)], Host=[localhost:8080]} response {Connection=[keep-alive], Transfer-Encoding=[chunked], Content-Type=[application/json;charset=UTF-8], Date=[Wed, 07 Nov 2018 13:50:23 GMT]}} : TRACE : XNIO-1 task-4 : io.undertow.server.HttpServerExchange
13:50:23.334 RequestSpecificationImpl$RestAssuredHttpBuilder : Parsing response as: application/json;charset=UTF-8 : DEBUG : main : io.restassured.internal.http.HTTPBuilder
13:50:23.341 RequestSpecificationImpl$RestAssuredHttpBuilder : Parsed data to instance of: class org.apache.http.conn.EofSensorInputStream : DEBUG : main : io.restassured.internal.http.HTTPBuilder
HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked
Content-Type: application/json;charset=UTF-8
Date: Wed, 07 Nov 2018 13:50:23 GMT
[
]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.974 s - in com.megacorp.widget.rest.WidgetSaveTests
13:50:24.343 io : Error reading request : DEBUG : XNIO-1 I/O-4 : io.undertow.server.protocol.http.HttpReadListener
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at org.xnio.nio.NioSocketConduit.read(NioSocketConduit.java:319)
at org.xnio.conduits.ConduitStreamSourceChannel.read(ConduitStreamSourceChannel.java:127)
at io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:158)
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:59)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)
13:50:24.343 io : Error reading request : DEBUG : XNIO-1 I/O-3 : io.undertow.server.protocol.http.HttpReadListener
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at org.xnio.nio.NioSocketConduit.read(NioSocketConduit.java:319)
at org.xnio.conduits.ConduitStreamSourceChannel.read(ConduitStreamSourceChannel.java:127)
at io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:158)
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:59)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:java (post-int-test) @ gem-widget ---
13:50:24.749 request : Opened connection with /127.0.0.1:58182 : TRACE : XNIO-1 I/O-1 : io.undertow.server.protocol.http.HttpOpenListener
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.1:verify (default) @ gem-widget ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 55.591 s
[INFO] Finished at: 2018-11-07T13:50:24+00:00
[INFO] Final Memory: 57M/616M
[INFO] ------------------------------------------------------------------------
Disconnected from the target VM, address: '127.0.0.1:58132', transport: 'socket'
FATAL ERROR in native method: JDWP Can't allocate jvmti memory, jvmtiError=JVMTI_ERROR_INVALID_ENVIRONMENT(116)
JDWP exit error JVMTI_ERROR_WRONG_PHASE(112): on getting class status [util.c:1285]
JDWP exit error JVMTI_ERROR_INVALID_ENVIRONMENT(116): Can't allocate jvmti memory [util.c:1799]
ERROR: JDWP unable to dispose of JVMTI environment: JVMTI_ERROR_INVALID_ENVIRONMENT(116)
Process finished with exit code 1