This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit af65aba8283168981e97f744e59c8f7c9ba21eaa
Author: Otavio Rodolfo Piske <[email protected]>
AuthorDate: Tue Jan 27 16:46:33 2026 +0000

    Add tests for camel-console module to increase coverage
    
    Add comprehensive test suite for the camel-console module:
    - Add AbstractDevConsoleTest base class with helper methods
    - Create SimpleDevConsoleTest parameterized test for 23 simple consoles
    - Create RouteBasedDevConsoleTest parameterized test for 8 route consoles
    - Add 16 new test files covering most DevConsole implementations
    - Add ~130 test methods testing both TEXT and JSON output formats
    - Add tests for Configurer classes (auto-generated property configurers)
    - Add camel-management as test dependency to enable JMX support
    - Coverage increased from ~9% to ~37%
    
    Note: Some console classes (ProcessorDevConsole, ProducerDevConsole,
    EventConsole) require full JMX MBean infrastructure that isn't easily
    available in unit tests without significant setup. Further coverage
    improvements would require integration tests with full JMX management.
---
 core/camel-console/pom.xml                         |   5 +
 .../camel/impl/console/AbstractDevConsoleTest.java | 102 ++++++++
 .../camel/impl/console/BeanDevConsoleTest.java     | 238 ++++++++++++++++++
 .../camel/impl/console/BrowseDevConsoleTest.java   | 239 ++++++++++++++++++
 .../apache/camel/impl/console/ConfigurerTest.java  | 276 +++++++++++++++++++++
 .../camel/impl/console/ConsoleHelperTest.java      | 107 ++++++++
 .../console/DefaultDevConsoleRegistryTest.java     |  78 ++++++
 .../impl/console/PropertiesDevConsoleTest.java     |  54 ++++
 .../camel/impl/console/ReceiveDevConsoleTest.java  |  43 ++++
 .../impl/console/RouteBasedDevConsoleTest.java     |  84 +++++++
 .../camel/impl/console/RouteDevConsoleTest.java    |  98 ++++++++
 .../camel/impl/console/SendDevConsoleTest.java     | 156 ++++++++++++
 .../camel/impl/console/SimpleDevConsoleTest.java   |  90 +++++++
 .../camel/impl/console/ThreadDevConsoleTest.java   |  94 +++++++
 .../impl/console/VariablesDevConsoleTest.java      |  50 ++++
 15 files changed, 1714 insertions(+)

diff --git a/core/camel-console/pom.xml b/core/camel-console/pom.xml
index 38dfa06e19b6..d99dc8227466 100644
--- a/core/camel-console/pom.xml
+++ b/core/camel-console/pom.xml
@@ -57,6 +57,11 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-management</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/AbstractDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/AbstractDevConsoleTest.java
new file mode 100644
index 000000000000..e93a7e6afa4c
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/AbstractDevConsoleTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.json.JsonObject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Base class for DevConsole tests providing common helper methods.
+ */
+public abstract class AbstractDevConsoleTest extends ContextTestSupport {
+
+    /**
+     * Resolves a DevConsole by its ID.
+     */
+    protected DevConsole resolveConsole(String consoleId) {
+        return 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole(consoleId);
+    }
+
+    /**
+     * Verifies that a console exists and has the expected ID.
+     */
+    protected DevConsole assertConsoleExists(String consoleId) {
+        DevConsole console = resolveConsole(consoleId);
+        assertNotNull(console, "Console '" + consoleId + "' should exist");
+        assertNotNull(console.getGroup(), "Console group should not be null");
+        assertEquals(consoleId, console.getId(), "Console ID should match");
+        return console;
+    }
+
+    /**
+     * Verifies that a console exists with the expected group and ID.
+     */
+    protected DevConsole assertConsoleExists(String consoleId, String 
expectedGroup) {
+        DevConsole console = resolveConsole(consoleId);
+        assertNotNull(console, "Console '" + consoleId + "' should exist");
+        assertEquals(expectedGroup, console.getGroup(), "Console group should 
match");
+        assertEquals(consoleId, console.getId(), "Console ID should match");
+        return console;
+    }
+
+    /**
+     * Calls a console with TEXT media type and verifies output is not null.
+     */
+    protected String callText(DevConsole console) {
+        String out = (String) console.call(DevConsole.MediaType.TEXT);
+        assertNotNull(out, "TEXT output should not be null");
+        log.info(out);
+        return out;
+    }
+
+    /**
+     * Calls a console with TEXT media type and options.
+     */
+    protected String callText(DevConsole console, Map<String, Object> options) 
{
+        String out = (String) console.call(DevConsole.MediaType.TEXT, options);
+        assertNotNull(out, "TEXT output should not be null");
+        log.info(out);
+        return out;
+    }
+
+    /**
+     * Calls a console with JSON media type and verifies output is not null.
+     */
+    protected JsonObject callJson(DevConsole console) {
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON);
+        assertNotNull(out, "JSON output should not be null");
+        log.info(out.toJson());
+        return out;
+    }
+
+    /**
+     * Calls a console with JSON media type and options.
+     */
+    protected JsonObject callJson(DevConsole console, Map<String, Object> 
options) {
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        assertNotNull(out, "JSON output should not be null");
+        log.info(out.toJson());
+        return out;
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/BeanDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/BeanDevConsoleTest.java
new file mode 100644
index 000000000000..68a9a6b043d1
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/BeanDevConsoleTest.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class BeanDevConsoleTest extends ContextTestSupport {
+
+    @Override
+    protected void doPostSetup() {
+        context.getRegistry().bind("myBean", new TestBean("Hello", 42));
+        context.getRegistry().bind("anotherBean", new TestBean("World", null));
+    }
+
+    @Test
+    public void testBeanConsoleText() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+        Assertions.assertEquals("camel", console.getGroup());
+        Assertions.assertEquals("bean", console.getId());
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        Assertions.assertTrue(out.contains("myBean"));
+        Assertions.assertTrue(out.contains("anotherBean"));
+        Assertions.assertTrue(out.contains("TestBean"));
+    }
+
+    @Test
+    public void testBeanConsoleJson() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonObject beans = out.getMap("beans");
+        Assertions.assertNotNull(beans);
+        Assertions.assertTrue(beans.containsKey("myBean"));
+        Assertions.assertTrue(beans.containsKey("anotherBean"));
+
+        JsonObject myBean = beans.getMap("myBean");
+        Assertions.assertEquals("myBean", myBean.getString("name"));
+        Assertions.assertTrue(myBean.getString("type").contains("TestBean"));
+    }
+
+    @Test
+    public void testBeanConsoleWithFilter() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.FILTER, "myBean");
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT, options);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        Assertions.assertTrue(out.contains("myBean"));
+        Assertions.assertFalse(out.contains("anotherBean"));
+    }
+
+    @Test
+    public void testBeanConsoleWithoutProperties() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.PROPERTIES, "false");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+
+        JsonObject beans = out.getMap("beans");
+        JsonObject myBean = beans.getMap("myBean");
+        Assertions.assertNotNull(myBean);
+        // No properties should be present
+        Assertions.assertFalse(myBean.containsKey("properties"));
+    }
+
+    @Test
+    public void testBeanConsoleWithProperties() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.PROPERTIES, "true");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonObject beans = out.getMap("beans");
+        JsonObject myBean = beans.getMap("myBean");
+        Assertions.assertNotNull(myBean);
+
+        JsonArray properties = myBean.getCollection("properties");
+        Assertions.assertNotNull(properties);
+        Assertions.assertFalse(properties.isEmpty());
+    }
+
+    @Test
+    public void testBeanConsoleWithNulls() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.FILTER, "anotherBean");
+        options.put(BeanDevConsole.NULLS, "true");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonObject beans = out.getMap("beans");
+        JsonObject anotherBean = beans.getMap("anotherBean");
+        Assertions.assertNotNull(anotherBean);
+
+        JsonArray properties = anotherBean.getCollection("properties");
+        Assertions.assertNotNull(properties);
+        // Should include null value properties
+        boolean hasNullValue = properties.stream()
+                .map(p -> (JsonObject) p)
+                .anyMatch(p -> p.get("value") == null);
+        Assertions.assertTrue(hasNullValue);
+    }
+
+    @Test
+    public void testBeanConsoleWithoutNulls() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.FILTER, "anotherBean");
+        options.put(BeanDevConsole.NULLS, "false");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonObject beans = out.getMap("beans");
+        JsonObject anotherBean = beans.getMap("anotherBean");
+        Assertions.assertNotNull(anotherBean);
+
+        JsonArray properties = anotherBean.getCollection("properties");
+        if (properties != null) {
+            // Should NOT include null value properties
+            boolean hasNullValue = properties.stream()
+                    .map(p -> (JsonObject) p)
+                    .anyMatch(p -> p.get("value") == null);
+            Assertions.assertFalse(hasNullValue);
+        }
+    }
+
+    @Test
+    public void testBeanConsoleExcludeInternal() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.INTERNAL, "false");
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT, options);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        // Our test beans are in org.apache.camel package, so they are treated 
as internal
+        // and should be excluded when internal=false
+        Assertions.assertFalse(out.contains("myBean"));
+        Assertions.assertFalse(out.contains("anotherBean"));
+    }
+
+    @Test
+    public void testBeanConsoleIncludeInternal() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("bean");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BeanDevConsole.INTERNAL, "true");
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT, options);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        // When internal=true, all beans including our test beans should be 
present
+        Assertions.assertTrue(out.contains("myBean"));
+        Assertions.assertTrue(out.contains("anotherBean"));
+    }
+
+    public static class TestBean {
+        private String name;
+        private Integer count;
+
+        public TestBean(String name, Integer count) {
+            this.name = name;
+            this.count = count;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public Integer getCount() {
+            return count;
+        }
+
+        public void setCount(Integer count) {
+            this.count = count;
+        }
+    }
+
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/BrowseDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/BrowseDevConsoleTest.java
new file mode 100644
index 000000000000..ff127b2e9199
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/BrowseDevConsoleTest.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class BrowseDevConsoleTest extends ContextTestSupport {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start")
+                        .to("seda:queue1");
+
+                from("direct:other")
+                        .to("seda:queue2");
+            }
+        };
+    }
+
+    @Test
+    public void testBrowseConsoleText() throws Exception {
+        // Send some messages to the seda queue
+        template.sendBody("direct:start", "Message 1");
+        template.sendBody("direct:start", "Message 2");
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+        Assertions.assertEquals("camel", console.getGroup());
+        Assertions.assertEquals("browse", console.getId());
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        Assertions.assertTrue(out.contains("seda://queue1"));
+    }
+
+    @Test
+    public void testBrowseConsoleJson() throws Exception {
+        // Send some messages to the seda queue
+        template.sendBody("direct:start", "Message 1");
+        template.sendBody("direct:start", "Message 2");
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        // Find queue1
+        boolean foundQueue1 = browse.stream()
+                .map(o -> (JsonObject) o)
+                .anyMatch(jo -> 
jo.getString("endpointUri").contains("queue1"));
+        Assertions.assertTrue(foundQueue1);
+    }
+
+    @Test
+    public void testBrowseConsoleWithFilter() throws Exception {
+        // Send messages to both queues
+        template.sendBody("direct:start", "Message for queue1");
+        template.sendBody("direct:other", "Message for queue2");
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT, options);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        Assertions.assertTrue(out.contains("queue1"));
+        Assertions.assertFalse(out.contains("queue2"));
+    }
+
+    @Test
+    public void testBrowseConsoleWithLimit() throws Exception {
+        // Send multiple messages
+        for (int i = 1; i <= 5; i++) {
+            template.sendBody("direct:start", "Message " + i);
+        }
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.LIMIT, "2");
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        JsonObject endpoint = (JsonObject) browse.get(0);
+        Assertions.assertEquals(2, endpoint.getInteger("limit").intValue());
+    }
+
+    @Test
+    public void testBrowseConsoleStatusOnly() throws Exception {
+        // Send some messages
+        template.sendBody("direct:start", "Message 1");
+        template.sendBody("direct:start", "Message 2");
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.DUMP, "false");
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        JsonObject endpoint = (JsonObject) browse.get(0);
+        // Status only should have queueSize but no messages array
+        Assertions.assertTrue(endpoint.containsKey("queueSize"));
+        Assertions.assertFalse(endpoint.containsKey("messages"));
+    }
+
+    @Test
+    public void testBrowseConsoleWithMessages() throws Exception {
+        // Send some messages
+        template.sendBody("direct:start", "Test Body Content");
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.DUMP, "true");
+        options.put(BrowseDevConsole.INCLUDE_BODY, "true");
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        JsonObject endpoint = (JsonObject) browse.get(0);
+        Assertions.assertTrue(endpoint.containsKey("messages"));
+
+        JsonArray messages = endpoint.getCollection("messages");
+        Assertions.assertNotNull(messages);
+        Assertions.assertFalse(messages.isEmpty());
+    }
+
+    @Test
+    public void testBrowseConsoleWithTail() throws Exception {
+        // Send multiple messages
+        for (int i = 1; i <= 5; i++) {
+            template.sendBody("direct:start", "Message " + i);
+        }
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.TAIL, "2");
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        JsonObject endpoint = (JsonObject) browse.get(0);
+        // Position should indicate we started from later in the queue
+        int position = endpoint.getInteger("position");
+        Assertions.assertTrue(position > 0);
+    }
+
+    @Test
+    public void testBrowseConsoleEmptyQueue() throws Exception {
+        // Don't send any messages, queue should be empty
+
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("browse");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(BrowseDevConsole.FILTER, ".*queue1.*");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        JsonArray browse = out.getCollection("browse");
+        Assertions.assertNotNull(browse);
+        Assertions.assertFalse(browse.isEmpty());
+
+        JsonObject endpoint = (JsonObject) browse.get(0);
+        Assertions.assertEquals(0, 
endpoint.getInteger("queueSize").intValue());
+    }
+
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/ConfigurerTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ConfigurerTest.java
new file mode 100644
index 000000000000..a41773d5d62f
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ConfigurerTest.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ConfigurerTest extends ContextTestSupport {
+
+    @Test
+    public void testSendDevConsoleConfigurer() {
+        SendDevConsoleConfigurer configurer = new SendDevConsoleConfigurer();
+        SendDevConsole console = new SendDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"bodyMaxChars", "1000", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"pollTimeout", "5000", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test with ignore case
+        Assertions.assertTrue(configurer.configure(context, console, 
"bodymaxchars", "2000", true));
+        Assertions.assertTrue(configurer.configure(context, console, 
"polltimeout", "6000", true));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+        Assertions.assertTrue(options.containsKey("BodyMaxChars"));
+        Assertions.assertTrue(options.containsKey("PollTimeout"));
+
+        // Test getOptionType
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("bodyMaxChars", false));
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("pollTimeout", false));
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"bodyMaxChars", false));
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"pollTimeout", false));
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testReceiveDevConsoleConfigurer() {
+        ReceiveDevConsoleConfigurer configurer = new 
ReceiveDevConsoleConfigurer();
+        ReceiveDevConsole console = new ReceiveDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"capacity", "200", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"bodyMaxChars", "1000", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"removeOnDump", "false", false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test with ignore case
+        Assertions.assertTrue(configurer.configure(context, console, 
"CAPACITY", "300", true));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+        Assertions.assertTrue(options.containsKey("Capacity"));
+
+        // Test getOptionType
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("capacity", false));
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("bodyMaxChars", false));
+        Assertions.assertEquals(boolean.class, 
configurer.getOptionType("removeOnDump", false));
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"capacity", false));
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"bodyMaxChars", false));
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"removeOnDump", false));
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testTraceDevConsoleConfigurer() {
+        TraceDevConsoleConfigurer configurer = new TraceDevConsoleConfigurer();
+        TraceDevConsole console = new TraceDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"capacity", "200", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("capacity", false));
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"capacity", false));
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testEventConsoleConfigurer() {
+        EventConsoleConfigurer configurer = new EventConsoleConfigurer();
+        EventConsole console = new EventConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"capacity", "200", false));
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertEquals(int.class, 
configurer.getOptionType("capacity", false));
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNotNull(configurer.getOptionValue(console, 
"capacity", false));
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testJvmDevConsoleConfigurer() {
+        JvmDevConsoleConfigurer configurer = new JvmDevConsoleConfigurer();
+        JvmDevConsole console = new JvmDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testMemoryDevConsoleConfigurer() {
+        MemoryDevConsoleConfigurer configurer = new 
MemoryDevConsoleConfigurer();
+        MemoryDevConsole console = new MemoryDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testThreadDevConsoleConfigurer() {
+        ThreadDevConsoleConfigurer configurer = new 
ThreadDevConsoleConfigurer();
+        ThreadDevConsole console = new ThreadDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testGarbageCollectorDevConsoleConfigurer() {
+        GarbageCollectorDevConsoleConfigurer configurer = new 
GarbageCollectorDevConsoleConfigurer();
+        GarbageCollectorDevConsole console = new GarbageCollectorDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testSystemPropertiesDevConsoleConfigurer() {
+        SystemPropertiesDevConsoleConfigurer configurer = new 
SystemPropertiesDevConsoleConfigurer();
+        SystemPropertiesDevConsole console = new SystemPropertiesDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testJavaSecurityDevConsoleConfigurer() {
+        JavaSecurityDevConsoleConfigurer configurer = new 
JavaSecurityDevConsoleConfigurer();
+        JavaSecurityDevConsole console = new JavaSecurityDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+
+    @Test
+    public void testMessageHistoryDevConsoleConfigurer() {
+        MessageHistoryDevConsoleConfigurer configurer = new 
MessageHistoryDevConsoleConfigurer();
+        MessageHistoryDevConsole console = new MessageHistoryDevConsole();
+
+        // Test configure
+        Assertions.assertTrue(configurer.configure(context, console, 
"camelContext", context, false));
+        Assertions.assertFalse(configurer.configure(context, console, 
"nonExistent", "value", false));
+
+        // Test getAllOptions
+        Map<String, Object> options = configurer.getAllOptions(console);
+        Assertions.assertNotNull(options);
+
+        // Test getOptionType
+        Assertions.assertNull(configurer.getOptionType("nonExistent", false));
+
+        // Test getOptionValue
+        Assertions.assertNull(configurer.getOptionValue(console, 
"nonExistent", false));
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/ConsoleHelperTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ConsoleHelperTest.java
new file mode 100644
index 000000000000..b4153031d711
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ConsoleHelperTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.List;
+
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ConsoleHelperTest {
+
+    @Test
+    public void testExtractSourceLocationLineNumber() {
+        Integer lineNumber = 
ConsoleHelper.extractSourceLocationLineNumber("file.java:42");
+        Assertions.assertEquals(42, lineNumber);
+    }
+
+    @Test
+    public void testExtractSourceLocationLineNumberNoNumber() {
+        Integer lineNumber = 
ConsoleHelper.extractSourceLocationLineNumber("file.java");
+        Assertions.assertNull(lineNumber);
+    }
+
+    @Test
+    public void testExtractSourceLocationLineNumberMultipleColons() {
+        Integer lineNumber = 
ConsoleHelper.extractSourceLocationLineNumber("classpath:com/example/file.java:100");
+        Assertions.assertEquals(100, lineNumber);
+    }
+
+    @Test
+    public void testExtractSourceLocationLineNumberInvalid() {
+        Integer lineNumber = 
ConsoleHelper.extractSourceLocationLineNumber("file.java:abc");
+        Assertions.assertNull(lineNumber);
+    }
+
+    @Test
+    public void testLoadSourceAsJsonFromReader() {
+        String source = "line one\nline two\nline three";
+        StringReader reader = new StringReader(source);
+
+        List<JsonObject> result = ConsoleHelper.loadSourceAsJson(reader, 2);
+        Assertions.assertNotNull(result);
+        Assertions.assertEquals(3, result.size());
+
+        JsonObject line1 = result.get(0);
+        Assertions.assertEquals(1, line1.getInteger("line"));
+        Assertions.assertEquals("line one", line1.getString("code"));
+        Assertions.assertNull(line1.get("match"));
+
+        JsonObject line2 = result.get(1);
+        Assertions.assertEquals(2, line2.getInteger("line"));
+        Assertions.assertEquals("line two", line2.getString("code"));
+        Assertions.assertTrue(line2.getBoolean("match"));
+
+        JsonObject line3 = result.get(2);
+        Assertions.assertEquals(3, line3.getInteger("line"));
+        Assertions.assertEquals("line three", line3.getString("code"));
+        Assertions.assertNull(line3.get("match"));
+    }
+
+    @Test
+    public void testLoadSourceAsJsonFromReaderNoLineNumber() {
+        String source = "line one\nline two";
+        StringReader reader = new StringReader(source);
+
+        List<JsonObject> result = ConsoleHelper.loadSourceAsJson(reader, null);
+        Assertions.assertNotNull(result);
+        Assertions.assertEquals(2, result.size());
+
+        // No match should be set when lineNumber is null
+        for (JsonObject jo : result) {
+            Assertions.assertNull(jo.get("match"));
+        }
+    }
+
+    @Test
+    public void testLoadSourceAsJsonFromReaderEmpty() {
+        StringReader reader = new StringReader("");
+
+        List<JsonObject> result = ConsoleHelper.loadSourceAsJson(reader, 1);
+        Assertions.assertNull(result);
+    }
+
+    @Test
+    public void testLoadSourceAsJsonNullReader() {
+        Reader nullReader = null;
+        List<JsonObject> result = ConsoleHelper.loadSourceAsJson(nullReader, 
1);
+        Assertions.assertNull(result);
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
new file mode 100644
index 000000000000..c77b8c7db368
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.console.DevConsoleRegistry;
+import org.apache.camel.support.PluginHelper;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class DefaultDevConsoleRegistryTest extends ContextTestSupport {
+
+    @Test
+    public void testRegistry() {
+        DevConsoleRegistry registry = 
context.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
+        Assertions.assertNotNull(registry);
+        Assertions.assertTrue(registry instanceof DefaultDevConsoleRegistry);
+        Assertions.assertTrue(registry.isEnabled());
+    }
+
+    @Test
+    public void testGetConsoles() {
+        DevConsoleRegistry registry = 
context.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
+        Assertions.assertNotNull(registry);
+
+        // The registry stream should not be empty after console loading
+        registry.loadDevConsoles();
+        long count = registry.stream().count();
+        Assertions.assertTrue(count >= 0);
+    }
+
+    @Test
+    public void testResolveConsoleById() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("context");
+        Assertions.assertNotNull(console);
+        Assertions.assertEquals("context", console.getId());
+        Assertions.assertEquals("camel", console.getGroup());
+    }
+
+    @Test
+    public void testRegisterAndUnregister() {
+        DevConsoleRegistry registry = 
context.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
+        Assertions.assertNotNull(registry);
+
+        // Create a custom console
+        DevConsole customConsole = new ContextDevConsole() {
+            @Override
+            public String getId() {
+                return "custom-test";
+            }
+        };
+
+        // Register the console
+        boolean registered = registry.register(customConsole);
+        Assertions.assertTrue(registered);
+        Assertions.assertTrue(registry.getConsole("custom-test").isPresent());
+
+        // Unregister the console
+        boolean unregistered = registry.unregister(customConsole);
+        Assertions.assertTrue(unregistered);
+        Assertions.assertFalse(registry.getConsole("custom-test").isPresent());
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/PropertiesDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/PropertiesDevConsoleTest.java
new file mode 100644
index 000000000000..7c396a2fd04a
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/PropertiesDevConsoleTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for PropertiesDevConsole with properties configured.
+ */
+public class PropertiesDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        Properties props = new Properties();
+        props.put("myProp", "myValue");
+        props.put("anotherProp", "anotherValue");
+        context.getPropertiesComponent().setInitialProperties(props);
+        return context;
+    }
+
+    @Test
+    public void testPropertiesConsole() {
+        DevConsole console = assertConsoleExists("properties", "camel");
+
+        String textOut = callText(console);
+        assertTrue(textOut.contains("Properties loaded from locations:"));
+
+        JsonObject jsonOut = callJson(console);
+        assertNotNull(jsonOut.get("locations"));
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/ReceiveDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ReceiveDevConsoleTest.java
new file mode 100644
index 000000000000..c81502b34e4e
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ReceiveDevConsoleTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for ReceiveDevConsole.
+ */
+public class ReceiveDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Test
+    public void testReceiveConsoleBasic() {
+        DevConsole console = assertConsoleExists("receive", "camel");
+
+        String textOut = callText(console);
+        assertTrue(textOut.contains("Enabled:"));
+        assertTrue(textOut.contains("Total:"));
+
+        JsonObject jsonOut = callJson(console);
+        assertNotNull(jsonOut.get("enabled"));
+        assertNotNull(jsonOut.get("total"));
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteBasedDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteBasedDevConsoleTest.java
new file mode 100644
index 000000000000..09c315d3202e
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteBasedDevConsoleTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.stream.Stream;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Parameterized test for DevConsoles that require routes to be configured.
+ */
+public class RouteBasedDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").routeId("myRoute").routeGroup("myGroup")
+                        .to("log:foo")
+                        .to("mock:result");
+
+                from("direct:bar").routeId("barRoute")
+                        .to("mock:bar");
+            }
+        };
+    }
+
+    /**
+     * Provides test parameters: console ID, expected JSON key (nullable).
+     */
+    static Stream<Arguments> routeConsoleParameters() {
+        return Stream.of(
+                // Console ID, JSON key to verify (nullable)
+                Arguments.of("consumer", "consumers"),
+                Arguments.of("endpoint", "endpoints"),
+                Arguments.of("route", "routes"),
+                Arguments.of("route-controller", "routes"),
+                Arguments.of("route-dump", "routes"),
+                Arguments.of("route-group", "routeGroups"),
+                Arguments.of("route-structure", "routes"),
+                Arguments.of("source", "routes"));
+    }
+
+    @ParameterizedTest(name = "{0} console - TEXT output")
+    @MethodSource("routeConsoleParameters")
+    void testConsoleText(String consoleId, String expectedJsonKey) {
+        DevConsole console = assertConsoleExists(consoleId);
+        callText(console);
+    }
+
+    @ParameterizedTest(name = "{0} console - JSON output")
+    @MethodSource("routeConsoleParameters")
+    void testConsoleJson(String consoleId, String expectedJsonKey) {
+        DevConsole console = assertConsoleExists(consoleId);
+        JsonObject out = callJson(console);
+
+        if (expectedJsonKey != null) {
+            assertTrue(out.containsKey(expectedJsonKey),
+                    "JSON output should contain key '" + expectedJsonKey + 
"'");
+        }
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteDevConsoleTest.java
new file mode 100644
index 000000000000..cbaceec4ae09
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/RouteDevConsoleTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for RouteDevConsole with various options (filter, limit, processors, 
action).
+ */
+public class RouteDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").routeId("myRoute")
+                        .to("log:foo")
+                        .to("mock:result");
+
+                from("direct:bar").routeId("barRoute").routeGroup("myGroup")
+                        .to("mock:bar");
+            }
+        };
+    }
+
+    @Test
+    public void testRouteConsoleBasic() {
+        DevConsole console = assertConsoleExists("route", "camel");
+        callText(console);
+
+        JsonObject json = callJson(console);
+        assertTrue(json.containsKey("routes"));
+    }
+
+    @Test
+    public void testRouteConsoleWithFilter() {
+        DevConsole console = assertConsoleExists("route");
+
+        callText(console, Map.of(RouteDevConsole.FILTER, "myRoute"));
+        callJson(console, Map.of(RouteDevConsole.FILTER, "myRoute"));
+    }
+
+    @Test
+    public void testRouteConsoleWithLimit() {
+        DevConsole console = assertConsoleExists("route");
+
+        callText(console, Map.of(RouteDevConsole.LIMIT, "1"));
+        callJson(console, Map.of(RouteDevConsole.LIMIT, "1"));
+    }
+
+    @Test
+    public void testRouteConsoleWithProcessors() {
+        DevConsole console = assertConsoleExists("route");
+
+        callText(console, Map.of(RouteDevConsole.PROCESSORS, "true"));
+        callJson(console, Map.of(RouteDevConsole.PROCESSORS, "true"));
+    }
+
+    @Test
+    public void testRouteConsoleWithGroupFilter() {
+        DevConsole console = assertConsoleExists("route");
+        callText(console, Map.of(RouteDevConsole.FILTER, "myGroup"));
+    }
+
+    @Test
+    public void testRouteConsoleWithWildcardFilter() {
+        DevConsole console = assertConsoleExists("route");
+        callText(console, Map.of(RouteDevConsole.FILTER, "*Route"));
+    }
+
+    @Test
+    public void testRouteConsoleActionStop() {
+        DevConsole console = assertConsoleExists("route");
+        callText(console, Map.of(RouteDevConsole.ACTION, "stop", 
RouteDevConsole.FILTER, "barRoute"));
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/SendDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SendDevConsoleTest.java
new file mode 100644
index 000000000000..e0c988c0c5b8
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SendDevConsoleTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for SendDevConsole with various options (endpoint, body, exchange 
pattern, etc.).
+ */
+public class SendDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").routeId("myRoute")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Test
+    public void testSendConsoleBasic() {
+        DevConsole console = assertConsoleExists("send", "camel");
+
+        Map<String, Object> options = createOptions("direct:start", "Hello 
World");
+        String textOut = callText(console, options);
+        assertTrue(textOut.contains("Endpoint:"));
+        assertTrue(textOut.contains("Status:"));
+
+        JsonObject jsonOut = callJson(console, options);
+        assertNotNull(jsonOut.getString("status"));
+        assertNotNull(jsonOut.getString("endpoint"));
+    }
+
+    @Test
+    public void testSendConsoleInOutPattern() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("direct:start", "Hello");
+        options.put(SendDevConsole.EXCHANGE_PATTERN, "InOut");
+
+        callText(console, options);
+        JsonObject jsonOut = callJson(console, options);
+        assertNotNull(jsonOut.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleWithHeaders() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("direct:start", "Hello");
+        options.put("MyHeader", "MyValue");
+
+        JsonObject out = callJson(console, options);
+        assertNotNull(out.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleNoEndpoint() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = new HashMap<>();
+        options.put(SendDevConsole.BODY, "Hello");
+
+        JsonObject out = callJson(console, options);
+        assertNotNull(out.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleWithRouteIdPattern() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("myRoute", "Hello");
+        JsonObject out = callJson(console, options);
+        assertNotNull(out.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleWithPatternWildcard() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("direct:*", "Hello");
+        JsonObject out = callJson(console, options);
+        assertNotNull(out.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleToNonExistentEndpoint() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("nonexistent", "Hello");
+
+        String textOut = callText(console, options);
+        assertTrue(textOut.contains("Status: error"));
+
+        JsonObject jsonOut = callJson(console, options);
+        assertEquals("error", jsonOut.getString("status"));
+    }
+
+    @Test
+    public void testSendConsoleGettersSetters() {
+        SendDevConsole console = new SendDevConsole();
+
+        console.setBodyMaxChars(1000);
+        assertEquals(1000, console.getBodyMaxChars());
+
+        console.setPollTimeout(5000);
+        assertEquals(5000, console.getPollTimeout());
+    }
+
+    @Test
+    public void testSendConsoleWithBodyMaxChars() {
+        DevConsole console = assertConsoleExists("send");
+
+        Map<String, Object> options = createOptions("direct:start", "Hello");
+        options.put(SendDevConsole.EXCHANGE_PATTERN, "InOut");
+        options.put(SendDevConsole.BODY_MAX_CHARS, "100");
+
+        callText(console, options);
+        JsonObject jsonOut = callJson(console, options);
+        assertNotNull(jsonOut.getString("status"));
+    }
+
+    private Map<String, Object> createOptions(String endpoint, String body) {
+        Map<String, Object> options = new HashMap<>();
+        options.put(SendDevConsole.ENDPOINT, endpoint);
+        options.put(SendDevConsole.BODY, body);
+        return options;
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleDevConsoleTest.java
new file mode 100644
index 000000000000..018f85743a38
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/SimpleDevConsoleTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.stream.Stream;
+
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Parameterized test for simple DevConsoles that don't require special setup. 
Each console is tested for basic TEXT and
+ * JSON output functionality.
+ */
+public class SimpleDevConsoleTest extends AbstractDevConsoleTest {
+
+    /**
+     * Provides test parameters: console ID, optional text assertion, optional 
JSON key to check.
+     */
+    static Stream<Arguments> consoleParameters() {
+        return Stream.of(
+                // Console ID, text contains (nullable), JSON key to verify 
(nullable)
+                Arguments.of("blocked", "Blocked:", "blocked"),
+                Arguments.of("circuit-breaker", null, "circuitBreakers"),
+                Arguments.of("context", null, null),
+                Arguments.of("debug", null, null),
+                Arguments.of("gc", null, "garbageCollectors"),
+                Arguments.of("health", null, "checks"),
+                Arguments.of("inflight", "Inflight:", "inflight"),
+                Arguments.of("internal-tasks", null, null),
+                Arguments.of("java-security", null, "securityProviders"),
+                Arguments.of("jvm", null, null),
+                Arguments.of("log", null, null),
+                Arguments.of("memory", null, null),
+                Arguments.of("message-history", null, null),
+                Arguments.of("reload", null, null),
+                Arguments.of("rest", null, null),
+                Arguments.of("service", null, null),
+                Arguments.of("startup-recorder", null, null),
+                Arguments.of("system-properties", null, null),
+                Arguments.of("thread", null, null),
+                Arguments.of("top", null, null),
+                Arguments.of("trace", null, null),
+                Arguments.of("transformers", null, null),
+                Arguments.of("type-converters", null, null));
+    }
+
+    @ParameterizedTest(name = "{0} console - TEXT output")
+    @MethodSource("consoleParameters")
+    void testConsoleText(String consoleId, String expectedTextContent, String 
expectedJsonKey) {
+        DevConsole console = assertConsoleExists(consoleId);
+        String out = callText(console);
+
+        if (expectedTextContent != null) {
+            assertTrue(out.contains(expectedTextContent),
+                    "TEXT output should contain '" + expectedTextContent + 
"'");
+        }
+    }
+
+    @ParameterizedTest(name = "{0} console - JSON output")
+    @MethodSource("consoleParameters")
+    void testConsoleJson(String consoleId, String expectedTextContent, String 
expectedJsonKey) {
+        DevConsole console = assertConsoleExists(consoleId);
+        JsonObject out = callJson(console);
+
+        if (expectedJsonKey != null) {
+            assertNotNull(out.get(expectedJsonKey),
+                    "JSON output should contain key '" + expectedJsonKey + 
"'");
+        }
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/ThreadDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ThreadDevConsoleTest.java
new file mode 100644
index 000000000000..d68143c2b3d4
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/ThreadDevConsoleTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ThreadDevConsoleTest extends ContextTestSupport {
+
+    @Test
+    public void testThreadConsoleText() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("thread");
+        Assertions.assertNotNull(console);
+        Assertions.assertEquals("jvm", console.getGroup());
+        Assertions.assertEquals("thread", console.getId());
+
+        String out = (String) console.call(DevConsole.MediaType.TEXT);
+        Assertions.assertNotNull(out);
+        log.info(out);
+        Assertions.assertTrue(out.contains("Threads:"));
+        Assertions.assertTrue(out.contains("Daemon Threads:"));
+        Assertions.assertTrue(out.contains("Total Started Threads:"));
+        Assertions.assertTrue(out.contains("Peak Threads:"));
+    }
+
+    @Test
+    public void testThreadConsoleJson() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("thread");
+        Assertions.assertNotNull(console);
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON);
+        Assertions.assertNotNull(out);
+        log.info(out.toJson());
+
+        Assertions.assertNotNull(out.get("threadCount"));
+        Assertions.assertNotNull(out.get("daemonThreadCount"));
+        Assertions.assertNotNull(out.get("totalStartedThreadCount"));
+        Assertions.assertNotNull(out.get("peakThreadCount"));
+
+        JsonArray threads = out.getCollection("threads");
+        Assertions.assertNotNull(threads);
+        Assertions.assertFalse(threads.isEmpty());
+
+        // Check first thread has required fields
+        JsonObject thread = (JsonObject) threads.get(0);
+        Assertions.assertNotNull(thread.get("id"));
+        Assertions.assertNotNull(thread.getString("name"));
+        Assertions.assertNotNull(thread.getString("state"));
+    }
+
+    @Test
+    public void testThreadConsoleWithStackTrace() {
+        DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("thread");
+        Assertions.assertNotNull(console);
+
+        Map<String, Object> options = new HashMap<>();
+        options.put("stackTrace", "true");
+
+        JsonObject out = (JsonObject) console.call(DevConsole.MediaType.JSON, 
options);
+        Assertions.assertNotNull(out);
+
+        JsonArray threads = out.getCollection("threads");
+        Assertions.assertNotNull(threads);
+        Assertions.assertFalse(threads.isEmpty());
+
+        // At least one thread should have a stack trace
+        boolean hasStackTrace = threads.stream()
+                .map(t -> (JsonObject) t)
+                .anyMatch(t -> t.containsKey("stackTrace"));
+        Assertions.assertTrue(hasStackTrace);
+    }
+}
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/VariablesDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/VariablesDevConsoleTest.java
new file mode 100644
index 000000000000..31eaae1adba1
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/VariablesDevConsoleTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.console;
+
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for VariablesDevConsole with variables configured.
+ */
+public class VariablesDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Override
+    protected void doPostSetup() {
+        context.setVariable("testVar", "testValue");
+        context.setVariable("anotherVar", 42);
+    }
+
+    @Test
+    public void testVariablesConsole() {
+        DevConsole console = assertConsoleExists("variables", "camel");
+
+        String textOut = callText(console);
+        assertTrue(textOut.contains("testVar"));
+        assertTrue(textOut.contains("testValue"));
+        assertTrue(textOut.contains("anotherVar"));
+        assertTrue(textOut.contains("42"));
+
+        JsonObject jsonOut = callJson(console);
+        assertFalse(jsonOut.isEmpty());
+    }
+}

Reply via email to