This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 1aaaa3766225 CAMEL-23889: Fix flaky camel-vertx-websocket surefire
tests
1aaaa3766225 is described below
commit 1aaaa3766225b3d3cfcb654084258fbeba9f5a74
Author: Guillaume Nodet <[email protected]>
AuthorDate: Sat Jul 4 12:12:57 2026 +0200
CAMEL-23889: Fix flaky camel-vertx-websocket surefire tests
* Fix flaky camel-vertx-websocket surefire tests
Replace Thread.sleep() calls with Awaitility-based async assertions
in the vertx-websocket reconnect tests, and fix an incorrect timeout
value in VertxWebSocketEventTest.
Changes:
- VertxWebsocketConsumerAsClientReconnectTest: Replace Thread.sleep(300)
with Awaitility await().untilAsserted() using fresh WebSocket
connections to bypass stale producer endpoint cache after server
restart.
- VertxWebsocketConsumerAsClientMaxReconnectTest: Replace
Thread.sleep(300) with Awaitility during(2, SECONDS) pattern to
reliably verify reconnect attempts are exhausted.
- VertxWebSocketEventTest: Fix timeout from 5000 seconds (83 minutes)
to 5 seconds in webSocketFuture.get() call.
- Add Awaitility test dependency to camel-vertx-websocket pom.xml.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* Simplify MaxReconnect test: replace during() with pollDelay()
The during().untilAsserted() pattern was correct but misleading — with
expectedMessageCount(0), assertIsSatisfied() passes immediately on every
poll, so during() was effectively just a timed wait. Use pollDelay()
instead which more clearly expresses the intent: wait for reconnect
attempts to exhaust, then verify.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* Fix pre-existing race in "verify send fails" assertions
After stopRoute("server"), the producer endpoint's cached WebSocket may
still appear open (isClosed() returns false) until the Vert.x event loop
processes the TCP close frame. Wrap the "verify that we cannot send
messages" assertion in Awaitility to wait until the close propagates,
and restore full end-to-end Camel flow in the reconnect test.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23889: Address review feedback on MockEndpoint assertions
- ReconnectTest: assertIsSatisfied(500) timeout was silently ignored
when expectedCount > 0 (defaults to 10s latch wait). Use
setResultWaitTime(500) to control the actual wait time.
- MaxReconnectTest: Replace Awaitility pollDelay wrapper with direct
assertIsSatisfied(2000) for the zero-count wait (simpler, equivalent).
Use setAssertPeriod(1000) for final assertion to re-verify after a
delay and catch late deliveries.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
.../camel-vertx/camel-vertx-websocket/pom.xml | 6 +++
.../vertx/websocket/VertxWebSocketEventTest.java | 2 +-
...xWebsocketConsumerAsClientMaxReconnectTest.java | 38 ++++++++++------
...ertxWebsocketConsumerAsClientReconnectTest.java | 50 +++++++++++++++-------
4 files changed, 67 insertions(+), 29 deletions(-)
diff --git a/components/camel-vertx/camel-vertx-websocket/pom.xml
b/components/camel-vertx/camel-vertx-websocket/pom.xml
index 109d111806c9..b7590aab6f32 100644
--- a/components/camel-vertx/camel-vertx-websocket/pom.xml
+++ b/components/camel-vertx/camel-vertx-websocket/pom.xml
@@ -55,6 +55,12 @@
<artifactId>camel-test-junit6</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <version>${awaitility-version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-main</artifactId>
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebSocketEventTest.java
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebSocketEventTest.java
index a998d451e0bd..d4cfa4969061 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebSocketEventTest.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebSocketEventTest.java
@@ -52,7 +52,7 @@ public class VertxWebSocketEventTest extends
VertxWebSocketTestSupport {
template.sendBody("vertx-websocket:localhost:" + port + "/test",
MESSAGE_BODY);
- ServerWebSocket webSocket = webSocketFuture.get(5000,
TimeUnit.SECONDS);
+ ServerWebSocket webSocket = webSocketFuture.get(5, TimeUnit.SECONDS);
assertNotNull(webSocket);
// Trigger error event (message length > max allowed)
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientMaxReconnectTest.java
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientMaxReconnectTest.java
index 1d5a173eb7d2..bdf1ecf4ed48 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientMaxReconnectTest.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientMaxReconnectTest.java
@@ -17,6 +17,7 @@
package org.apache.camel.component.vertx.websocket;
import java.net.ConnectException;
+import java.util.concurrent.TimeUnit;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
@@ -26,6 +27,8 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import static org.awaitility.Awaitility.await;
+
public class VertxWebsocketConsumerAsClientMaxReconnectTest extends
VertxWebSocketTestSupport {
@Test
void testMaxReconnect() throws Exception {
@@ -42,25 +45,36 @@ public class VertxWebsocketConsumerAsClientMaxReconnectTest
extends VertxWebSock
context.getRouteController().stopRoute("server");
- // Verify that we cannot send messages
- Exchange exchange = template.send(uri, new Processor() {
- @Override
- public void process(Exchange exchange) throws Exception {
- exchange.getMessage().setBody("Hello World Again");
- }
- });
- Exception exception = exchange.getException();
- Assertions.assertNotNull(exception);
- Assertions.assertInstanceOf(ConnectException.class,
exception.getCause());
+ // Verify that the server is fully down by waiting until sends fail.
+ // The producer endpoint's cached WebSocket may still appear open
briefly
+ // after stopRoute returns, until the Vert.x event loop processes the
+ // TCP close frame and isClosed() starts returning true.
+ await().atMost(10, TimeUnit.SECONDS)
+ .untilAsserted(() -> {
+ Exchange exchange = template.send(uri, new Processor() {
+ @Override
+ public void process(Exchange exchange) throws
Exception {
+ exchange.getMessage().setBody("Hello World Again");
+ }
+ });
+ Assertions.assertNotNull(exchange.getException());
+ Assertions.assertInstanceOf(ConnectException.class,
exchange.getException().getCause());
+ });
// Wait for client consumer reconnect max attempts to be exhausted
- Thread.sleep(300);
+ // (maxReconnectAttempts=1, reconnectInterval=10ms).
+ // With expectedMessageCount(0), assertIsSatisfied(2000) sleeps for
+ // 2 seconds then verifies no messages were received.
+ mockEndpoint.assertIsSatisfied(2000);
// Restart server
context.getRouteController().startRoute("server");
- // Verify that the client consumer gave up reconnecting
+ // Verify that the client consumer gave up reconnecting.
+ // Use setAssertPeriod to re-verify after a delay, catching any
+ // late deliveries that arrive after the initial assertion passes.
template.sendBody(uri, "Hello World Again");
+ mockEndpoint.setAssertPeriod(1000);
mockEndpoint.assertIsSatisfied();
}
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientReconnectTest.java
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientReconnectTest.java
index 1380be718dc7..e4d2de3e5911 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientReconnectTest.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientReconnectTest.java
@@ -17,6 +17,7 @@
package org.apache.camel.component.vertx.websocket;
import java.net.ConnectException;
+import java.util.concurrent.TimeUnit;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
@@ -26,6 +27,8 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import static org.awaitility.Awaitility.await;
+
public class VertxWebsocketConsumerAsClientReconnectTest extends
VertxWebSocketTestSupport {
@Test
void testReconnect() throws Exception {
@@ -42,26 +45,41 @@ public class VertxWebsocketConsumerAsClientReconnectTest
extends VertxWebSocketT
context.getRouteController().stopRoute("server");
- // Verify that we cannot send messages
- Exchange exchange = template.send(uri, new Processor() {
- @Override
- public void process(Exchange exchange) throws Exception {
- exchange.getMessage().setBody("Hello World Again");
- }
- });
- Exception exception = exchange.getException();
- Assertions.assertNotNull(exception);
- Assertions.assertInstanceOf(ConnectException.class,
exception.getCause());
+ // Verify that the server is fully down by waiting until sends fail.
+ // The producer endpoint's cached WebSocket may still appear open
briefly
+ // after stopRoute returns, until the Vert.x event loop processes the
+ // TCP close frame and isClosed() starts returning true.
+ await().atMost(10, TimeUnit.SECONDS)
+ .untilAsserted(() -> {
+ Exchange exchange = template.send(uri, new Processor() {
+ @Override
+ public void process(Exchange exchange) throws
Exception {
+ exchange.getMessage().setBody("Hello World Again");
+ }
+ });
+ Assertions.assertNotNull(exchange.getException());
+ Assertions.assertInstanceOf(ConnectException.class,
exchange.getException().getCause());
+ });
// Restart server
context.getRouteController().startRoute("server");
- // Wait for client consumer reconnect
- Thread.sleep(300);
-
- // Verify that the client consumer reconnected
- template.sendBody(uri, "Hello World Again");
- mockEndpoint.assertIsSatisfied();
+ // Wait for client consumer to reconnect and verify end-to-end message
flow.
+ // After the server stops, the client consumer's close handler fires
+ // asynchronously on the Vert.x event loop, starting the reconnect
timer
+ // that connects to the restarted server.
+ // Use ignoreExceptions() to retry through transient failures while
both
+ // the producer and client consumer re-establish their connections.
+ await().atMost(20, TimeUnit.SECONDS)
+ .pollInterval(500, TimeUnit.MILLISECONDS)
+ .ignoreExceptions()
+ .untilAsserted(() -> {
+ mockEndpoint.reset();
+ mockEndpoint.expectedBodiesReceived("Hello World Again");
+ mockEndpoint.setResultWaitTime(500);
+ template.sendBody(uri, "Hello World Again");
+ mockEndpoint.assertIsSatisfied();
+ });
}
@Override