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

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new ddb859036 Test modernization
ddb859036 is described below

commit ddb8590361d88d230796f84c5519ca3a3e301864
Author: James Bognar <[email protected]>
AuthorDate: Tue Sep 9 14:19:38 2025 -0400

    Test modernization
---
 .../src/test/java/org/apache/juneau/TestUtils.java | 76 +++++++++-------------
 .../apache/juneau/junit/BasicBeanConverter.java    | 26 +++++---
 .../org/apache/juneau/junit/BeanConverter.java     | 12 +---
 3 files changed, 50 insertions(+), 64 deletions(-)

diff --git a/juneau-utest/src/test/java/org/apache/juneau/TestUtils.java 
b/juneau-utest/src/test/java/org/apache/juneau/TestUtils.java
index 37fc5131a..1f6f06e84 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/TestUtils.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/TestUtils.java
@@ -12,7 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau;
 
-import static java.util.Optional.*;
 import static java.util.stream.Collectors.*;
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -39,11 +38,11 @@ import org.opentest4j.*;
 
 /**
  * Comprehensive utility class for Bean-Centric Tests (BCT) and general 
testing operations.
- * 
+ *
  * <p>This class provides the core testing infrastructure for Apache Juneau, 
with particular emphasis
  * on the Bean-Centric Testing (BCT) framework. BCT enables sophisticated 
assertion patterns for
  * testing object properties, collections, maps, and complex nested structures 
with minimal code.</p>
- * 
+ *
  * <h5 class='section'>Bean-Centric Testing (BCT) Framework:</h5>
  * <p>The BCT framework consists of several key components:</p>
  * <ul>
@@ -51,25 +50,25 @@ import org.opentest4j.*;
  *     <li><b>{@link BasicBeanConverter}:</b> Default implementation with 
extensible type handlers</li>
  *     <li><b>Assertion Methods:</b> High-level testing methods that leverage 
the converter framework</li>
  * </ul>
- * 
+ *
  * <h5 class='section'>Primary BCT Assertion Methods:</h5>
  * <dl>
  *     <dt><b>{@link #assertBean(Object, String, String)}</b></dt>
  *     <dd>Tests object properties with nested syntax support and collection 
iteration</dd>
- *     
+ *
  *     <dt><b>{@link #assertMap(Map, String, String)}</b></dt>
  *     <dd>Tests map entries with the same nested property syntax as 
assertBean</dd>
- *     
+ *
  *     <dt><b>{@link #assertMapped(Object, java.util.function.BiFunction, 
String, String)}</b></dt>
  *     <dd>Tests custom property access using BiFunction for non-standard 
objects</dd>
- *     
+ *
  *     <dt><b>{@link #assertList(List, Object...)}</b></dt>
  *     <dd>Tests list/collection elements with varargs for expected values</dd>
- *     
+ *
  *     <dt><b>{@link #assertBeans(Collection, String, String...)}</b></dt>
  *     <dd>Tests collections of objects by extracting and comparing specific 
fields</dd>
  * </dl>
- * 
+ *
  * <h5 class='section'>BCT Advanced Features:</h5>
  * <ul>
  *     <li><b>Nested Property Syntax:</b> "address{street,city}" for testing 
nested objects</li>
@@ -80,7 +79,7 @@ import org.opentest4j.*;
  *     <li><b>Direct Field Access:</b> Public fields accessed without 
getters</li>
  *     <li><b>Map Key Access:</b> Including special "&lt;NULL&gt;" syntax for 
null keys</li>
  * </ul>
- * 
+ *
  * <h5 class='section'>Converter Extensibility:</h5>
  * <p>The BCT framework is built on the extensible {@link BasicBeanConverter} 
which allows:</p>
  * <ul>
@@ -89,43 +88,43 @@ import org.opentest4j.*;
  *     <li><b>Custom Swapifiers:</b> Object transformation before 
conversion</li>
  *     <li><b>Configurable Settings:</b> Formatting, delimiters, and display 
options</li>
  * </ul>
- * 
+ *
  * <h5 class='section'>Usage Examples:</h5>
- * 
+ *
  * <p><b>Basic Property Testing:</b></p>
  * <p class='bjava'>
  *     <jc>// Test multiple properties</jc>
  *     assertBean(user, <js>"name,age,active"</js>, <js>"John,30,true"</js>);
- *     
+ *
  *     <jc>// Test nested properties</jc>
  *     assertBean(user, <js>"address{street,city}"</js>, <js>"{123 Main 
St,Springfield}"</js>);
  * </p>
- * 
+ *
  * <p><b>Collection and Array Testing:</b></p>
  * <p class='bjava'>
  *     <jc>// Test collection size and iterate over all elements</jc>
  *     assertBean(order, <js>"items{length,#{name}}"</js>, 
<js>"{3,[{Laptop},{Phone},{Tablet}]}"</js>);
- *     
+ *
  *     <jc>// Test specific array elements</jc>
  *     assertBean(data, <js>"values{0,1,2}"</js>, <js>"{100,200,300}"</js>);
  * </p>
- * 
+ *
  * <p><b>Map and Collection Testing:</b></p>
  * <p class='bjava'>
  *     <jc>// Test map entries</jc>
  *     assertMap(config, <js>"timeout,retries"</js>, <js>"30000,3"</js>);
- *     
+ *
  *     <jc>// Test list elements</jc>
  *     assertList(tags, <js>"red"</js>, <js>"green"</js>, <js>"blue"</js>);
  * </p>
- * 
+ *
  * <p><b>Custom Property Access:</b></p>
  * <p class='bjava'>
  *     <jc>// Test with custom accessor function</jc>
- *     assertMapped(myObject, (obj, prop) -> obj.getProperty(prop), 
+ *     assertMapped(myObject, (obj, prop) -> obj.getProperty(prop),
  *             <js>"prop1,prop2"</js>, <js>"value1,value2"</js>);
  * </p>
- * 
+ *
  * <h5 class='section'>Performance and Thread Safety:</h5>
  * <p>The BCT framework is designed for high performance with:</p>
  * <ul>
@@ -133,7 +132,7 @@ import org.opentest4j.*;
  *     <li><b>Thread Safety:</b> All operations are thread-safe for concurrent 
testing</li>
  *     <li><b>Minimal Allocation:</b> Efficient object reuse and minimal 
temporary objects</li>
  * </ul>
- * 
+ *
  * @see BeanConverter
  * @see BasicBeanConverter
  */
@@ -149,7 +148,7 @@ public class TestUtils extends Utils2 {
         * <p>This is the primary method for Bean-Centric Tests (BCT), 
supporting extensive property validation
         * patterns including nested objects, collections, arrays, method 
chaining, direct field access, collection iteration
         * with <js>#{property}</js> syntax, and universal 
<js>length</js>/<js>size</js> properties for all collection types.</p>
-        * 
+        *
         * <p>The method uses the {@link BasicBeanConverter#DEFAULT} converter 
internally for object introspection
         * and value extraction. The converter provides sophisticated property 
access through the {@link BeanConverter}
         * interface, supporting multiple fallback mechanisms for accessing 
object properties and values.</p>
@@ -322,7 +321,11 @@ public class TestUtils extends Utils2 {
                assertNotNull(actual, "Value was null.");
                assertArgNotNull("fields", fields);
                assertArgNotNull("expected", expected);
-               assertEquals(expected, splitNested(fields).stream().map(x -> 
getEntry(converter, actual, x)).collect(joining(",")));
+               assertEquals(expected, tokenize(fields).stream().map(x -> 
converter.getNested(actual, x)).collect(joining(",")));
+       }
+
+       private static List<NestedTokenizer.Token> tokenize(String fields) {
+               return NestedTokenizer.tokenize(fields);
        }
 
        /**
@@ -391,7 +394,7 @@ public class TestUtils extends Utils2 {
                assertArgNotNull("fields", fields);
                assertArgNotNull("expected", expected);
 
-               var f = splitNested(fields);
+               var tokens = tokenize(fields);
                var errors = new ArrayList<AssertionFailedError>();
                var actualList = converter.listify(actual);
 
@@ -400,7 +403,7 @@ public class TestUtils extends Utils2 {
                } else {
                        for (var i = 0; i < actualList.size(); i++) {
                                var i2 = i;
-                               var a = f.stream().map(x -> getEntry(converter, 
actualList.get(i2), x)).collect(joining(","));
+                               var a = tokens.stream().map(x -> 
converter.getNested(actualList.get(i2), x)).collect(joining(","));
                                if (ne(r(expected[i]), a)) {
                                        
errors.add(assertionFailed(r(expected[i]), a, "Bean at row {0} did not match.", 
i));
                                }
@@ -411,7 +414,7 @@ public class TestUtils extends Utils2 {
 
                var actualStrings = new ArrayList<String>();
                for (var o : actualList) {
-                       actualStrings.add(f.stream().map(x -> 
getEntry(converter, o, x)).collect(joining(",")));
+                       actualStrings.add(tokens.stream().map(x -> 
converter.getNested(o, x)).collect(joining(",")));
                }
 
                if (errors.size() == 1) throw errors.get(0);
@@ -660,7 +663,7 @@ public class TestUtils extends Utils2 {
                assertNotNull(actual, "Value was null.");
                assertArgNotNull("fields", fields);
                assertArgNotNull("expected", expected);
-               assertEquals(expected, splitNested(fields).stream().map(x -> 
getEntry(converter, actual, x)).collect(joining(",")));
+               assertEquals(expected, tokenize(fields).stream().map(x -> 
converter.getNested(actual, x)).collect(joining(",")));
        }
 
        /**
@@ -922,25 +925,6 @@ public class TestUtils extends Utils2 {
                return Stream.iterate(t, Throwable::getCause).takeWhile(e -> e 
!= null).map(Throwable::getMessage).collect(joining("\n"));
        }
 
-       private static String getEntry(BeanConverter converter, Object o, 
String name) {
-
-               if (o == null) return converter.nullValue();
-
-               // Handle #{...} syntax for iterating over collections/arrays
-               if (name.startsWith("#{") && name.endsWith("}") && 
converter.canListify(o)) {
-                       var spn = splitNestedInner(name);
-                       return converter.listify(o).stream().map(x -> 
spn.stream().map(x2 -> getEntry(converter, x, 
x2)).collect(joining(",","{","}"))).collect(joining(",","[","]"));
-               }
-
-               // Original logic for regular property access
-               var i = name.indexOf("{");
-               var pn = i == -1 ? name : name.substring(0, i);
-               var spn = i == -1 ? null : splitNestedInner(name);
-               var e = ofNullable(converter.getProperty(o, pn.equals("<NULL>") 
? null : pn)).orElse(null);
-               if (spn == null || e == null) return converter.stringify(e);
-               return spn.stream().map(x -> getEntry(converter, e, 
x)).map(converter::stringify).collect(joining(",","{","}"));
-       }
-
        /**
         * Gets the swagger for the specified @Resource-annotated object.
         * @param c
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/junit/BasicBeanConverter.java 
b/juneau-utest/src/test/java/org/apache/juneau/junit/BasicBeanConverter.java
index 43796bfe0..14dc23567 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/junit/BasicBeanConverter.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/junit/BasicBeanConverter.java
@@ -197,7 +197,6 @@ public class BasicBeanConverter implements BeanConverter {
 
        public static final String
                SETTING_nullValue = "nullValue",
-               SETTING_emptyValue = "emptyValue",
                SETTING_fieldSeparator = "fieldSeparator",
                SETTING_collectionPrefix = "collectionPrefix",
                SETTING_collectionSuffix = "collectionSuffix",
@@ -205,7 +204,7 @@ public class BasicBeanConverter implements BeanConverter {
                SETTING_mapSuffix = "mapSuffix",
                SETTING_mapEntrySeparator = "mapEntrySeparator",
                SETTING_calendarFormat = "calendarFormat",
-               SETTING_classNameFormat = "short";
+               SETTING_classNameFormat = "classNameFormat";
 
        private final List<StringifierEntry<?>> stringifiers;
        private final List<ListifierEntry<?>> listifiers;
@@ -289,11 +288,6 @@ public class BasicBeanConverter implements BeanConverter {
                return o instanceof List || c.isArray() || 
listifierMap.computeIfAbsent(c, this::findListifier).isPresent();
        }
 
-       @Override
-       public String nullValue() {
-               return getSetting(SETTING_nullValue, null);
-       }
-
        @Override
        public Object getProperty(Object object, String name) {
                var o = swap(object);
@@ -305,6 +299,23 @@ public class BasicBeanConverter implements BeanConverter {
                        .extract(this, o, name);
        }
 
+       @Override
+       public String getNested(Object o, NestedTokenizer.Token token) {
+
+               if (o == null) return getSetting(SETTING_nullValue, null);
+
+               // Handle #{...} syntax for iterating over collections/arrays
+               if (eq("#", token.getValue()) && canListify(o)) {
+                       return listify(o).stream().map(x -> 
token.getNested().stream().map(x2 -> getNested(x, 
x2)).collect(joining(",","{","}"))).collect(joining(",","[","]"));
+               }
+
+               // Original logic for regular property access
+               var pn = token.getValue();
+               var e = ofNullable(getProperty(o, pn.equals("<NULL>") ? null : 
pn)).orElse(null);
+               if (e == null || ! token.hasNested()) return stringify(e);
+               return token.getNested().stream().map(x -> getNested(e, 
x)).map(this::stringify).collect(joining(",","{","}"));
+       }
+
        private Optional<Stringifier<?>> findStringifier(Class<?> c) {
                if (c == null)
                        return empty();
@@ -491,7 +502,6 @@ public class BasicBeanConverter implements BeanConverter {
                 */
                public Builder defaultSettings() {
                        addSetting(SETTING_nullValue, "<null>");
-                       addSetting(SETTING_emptyValue, "<empty>");
                        addSetting(SETTING_classNameFormat, "simple");
 
                        addStringifier(Map.Entry.class, (bc, o) -> 
bc.stringify(o.getKey()) + bc.getSetting(SETTING_mapEntrySeparator, "=") + 
bc.stringify(o.getValue()));
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/junit/BeanConverter.java 
b/juneau-utest/src/test/java/org/apache/juneau/junit/BeanConverter.java
index 11845c097..5f16ff1aa 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/junit/BeanConverter.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/junit/BeanConverter.java
@@ -146,16 +146,6 @@ public interface BeanConverter {
         */
        boolean canListify(Object o);
 
-       /**
-        * Returns the string representation used for null values.
-        *
-        * <p>This is used by {@link #stringify(Object)} when the object (after 
swapping) is null.
-        * The default implementation typically returns "&lt;null&gt;" or 
similar.</p>
-        *
-        * @return The null value representation
-        */
-       String nullValue();
-
        /**
         * Pre-processes objects before conversion operations.
         *
@@ -209,4 +199,6 @@ public interface BeanConverter {
        Object getProperty(Object object, String name);
 
        <T> T getSetting(String key, T defaultValue);
+
+       String getNested(Object o, NestedTokenizer.Token token);
 }

Reply via email to