Skip to content

Commit ee8873e

Browse files
isidoreLarsEckart
andcommitted
- B Sort map keys by toString if not Comparable
Fixes #650 When verifying a Map using StringUtils.toString(), keys are now sorted by their toString() representation if they do not implement Comparable. This prevents ClassCastExceptions. Added a test case with non-comparable keys using inline approvals. Co-authored-by: Lars <LarsEckart@users.noreply.github.com>
1 parent 5c50f27 commit ee8873e

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

approvaltests-util-tests/src/test/java/com/spun/util/StringUtilsTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.junit.jupiter.api.Test;
99

1010
import java.util.Arrays;
11+
import java.util.HashMap;
1112
import java.util.List;
1213
import java.util.Map;
1314
import java.util.TreeMap;
@@ -101,6 +102,22 @@ void testSortedMap()
101102
sortedMap.put("zz", "1");
102103
Approvals.verify(sortedMap);
103104
}
105+
@Test
106+
void testMapWithNonComparableKeys()
107+
{
108+
var expected = """
109+
a : first
110+
m : middle
111+
z : last
112+
""";
113+
Map<NonComparableKey, String> map = new HashMap<>();
114+
// Add keys in a specific order to see if it's preserved or sorted later
115+
map.put(new NonComparableKey("z"), "last");
116+
map.put(new NonComparableKey("a"), "first");
117+
map.put(new NonComparableKey("m"), "middle");
118+
// Use inline approval with the expected sorted-by-toString output
119+
Approvals.verify(map, new Options().inline(expected).withReporter(new AutoApproveReporter()));
120+
}
104121
public class SplitUseCase
105122
{
106123
String start;
@@ -160,4 +177,17 @@ public void testEnsureEnding()
160177
assertEquals(StringUtils.ensureEnding(first, "\n"), second);
161178
assertEquals(StringUtils.ensureEnding(second, "\n"), second);
162179
}
180+
private static class NonComparableKey
181+
{
182+
private final String value;
183+
public NonComparableKey(String value)
184+
{
185+
this.value = value;
186+
}
187+
@Override
188+
public String toString()
189+
{
190+
return value;
191+
}
192+
}
163193
}

approvaltests-util/src/main/java/com/spun/util/StringUtils.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.lambda.functions.Function1;
44
import org.lambda.query.Query;
5+
import org.lambda.query.Queryable;
56

67
import java.io.ByteArrayInputStream;
78
import java.io.InputStream;
@@ -10,6 +11,7 @@
1011
import java.nio.charset.StandardCharsets;
1112
import java.util.Arrays;
1213
import java.util.Collection;
14+
import java.util.Comparator;
1315
import java.util.List;
1416
import java.util.Map;
1517
import java.util.Properties;
@@ -550,9 +552,17 @@ public static String toString(Map<?, ?> map)
550552
{
551553
StringBuffer b = new StringBuffer();
552554
Object[] keySet = map.keySet().toArray();
555+
boolean isKeyComparable = ArrayUtils.isEmpty(keySet) || keySet[0] instanceof Comparable;
553556
if (!(map instanceof SortedMap))
554557
{
555-
Arrays.sort(keySet);
558+
if (isKeyComparable)
559+
{
560+
Arrays.sort(keySet);
561+
}
562+
else
563+
{
564+
Arrays.sort(keySet, Comparator.comparing(Object::toString));
565+
}
556566
}
557567
for (Object key : keySet)
558568
{

0 commit comments

Comments
 (0)