1+ package com .baeldung .stringmap ;
2+
3+ import org .junit .jupiter .api .BeforeEach ;
4+ import org .junit .jupiter .api .Test ;
5+ import org .springframework .validation .Errors ;
6+ import org .springframework .validation .MapBindingResult ;
7+
8+ import java .util .HashMap ;
9+ import java .util .LinkedHashMap ;
10+ import java .util .Map ;
11+
12+ import static org .assertj .core .api .Assertions .assertThat ;
13+
14+ class MapValidatorTest {
15+ private MapValidator mapValidator ;
16+ private static final String OBJECT_NAME = "targetMap" ; // Consistent name for the binding result
17+
18+ @ BeforeEach
19+ void setUp () {
20+ mapValidator = new MapValidator ();
21+ }
22+
23+ @ Test
24+ void givenMapValidator_whenSupportsCalledWithMapClass_thenReturnsTrue () {
25+ assertThat (mapValidator .supports (Map .class )).isTrue ();
26+ assertThat (mapValidator .supports (HashMap .class )).isTrue (); // Also true for subclasses
27+ assertThat (mapValidator .supports (LinkedHashMap .class )).isTrue ();
28+ }
29+
30+ @ Test
31+ void givenMapValidator_whenSupportsCalledWithNonMapClass_thenReturnsFalse () {
32+ assertThat (mapValidator .supports (String .class )).isFalse ();
33+ assertThat (mapValidator .supports (Object .class )).isFalse ();
34+ assertThat (mapValidator .supports (Integer .class )).isFalse ();
35+ }
36+
37+ @ Test
38+ void givenValidMap_whenValidateIsCalled_thenValidationSucceeds () {
39+ Map <String , String > validMap = new LinkedHashMap <>();
40+ validMap .put ("longEnoughKey1" , "Valid Value 1" );
41+ validMap .put ("anotherValidKeyHere" , "Valid Value 2" );
42+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
43+
44+ mapValidator .validate (validMap , errors );
45+
46+ assertThat (errors .hasErrors ()).isFalse ();
47+ }
48+
49+ @ Test
50+ void givenMapWithNonStringKey_whenValidateIsCalled_thenRejectsWithInvalidTypeError () {
51+ Map <Object , Object > mapWithInvalidKey = new LinkedHashMap <>();
52+ mapWithInvalidKey .put (123 , "Value for integer key" ); // Invalid key type
53+ mapWithInvalidKey .put ("validKeyString" , "Valid Value" );
54+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
55+
56+ mapValidator .validate (mapWithInvalidKey , errors );
57+
58+ assertThat (errors .hasErrors ()).isTrue ();
59+ assertThat (errors .getErrorCount ()).isEqualTo (1 );
60+ assertThat (errors .getFieldError ("map[123]" )).isNotNull ();
61+ assertThat (errors .getFieldError ("map[123]" ).getCode ()).isEqualTo ("map.entry.invalidType" );
62+ }
63+
64+ @ Test
65+ void givenMapWithNonStringValue_whenValidateIsCalled_thenRejectsWithInvalidTypeError () {
66+ Map <Object , Object > mapWithInvalidValue = new LinkedHashMap <>();
67+ mapWithInvalidValue .put ("validKeyString1" , 12345 ); // Invalid value type
68+ mapWithInvalidValue .put ("validKeyString2" , "Valid Value" );
69+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
70+
71+ mapValidator .validate (mapWithInvalidValue , errors );
72+
73+ assertThat (errors .hasErrors ()).isTrue ();
74+ assertThat (errors .getErrorCount ()).isEqualTo (1 );
75+ assertThat (errors .getFieldError ("map[validKeyString1]" )).isNotNull ();
76+ assertThat (errors .getFieldError ("map[validKeyString1]" ).getCode ()).isEqualTo ("map.entry.invalidType" );
77+ }
78+
79+ @ Test
80+ void givenMapWithShortKey_whenValidateIsCalled_thenRejectsWithKeyTooShortError () {
81+ Map <String , String > mapWithShortKey = new LinkedHashMap <>();
82+ mapWithShortKey .put ("shortKey" , "Valid Value" ); // Key too short
83+ mapWithShortKey .put ("longEnoughKey1" , "Another Valid Value" );
84+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
85+
86+ mapValidator .validate (mapWithShortKey , errors );
87+
88+ assertThat (errors .hasErrors ()).isTrue ();
89+ assertThat (errors .getErrorCount ()).isEqualTo (1 );
90+ assertThat (errors .getFieldError ("map[shortKey]" )).isNotNull ();
91+ assertThat (errors .getFieldError ("map[shortKey]" ).getCode ()).isEqualTo ("key.tooShort" );
92+ }
93+
94+ @ Test
95+ void givenMapWithBlankValue_whenValidateIsCalled_thenRejectsWithValueBlankError () {
96+ Map <String , String > mapWithBlankValue = new LinkedHashMap <>();
97+ mapWithBlankValue .put ("longEnoughKey1" , "" ); // Blank value
98+ mapWithBlankValue .put ("longEnoughKey2" , " " ); // Blank value (whitespace)
99+ mapWithBlankValue .put ("longEnoughKey3" , "Valid Value" );
100+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
101+
102+ mapValidator .validate (mapWithBlankValue , errors );
103+
104+ // Then: Errors should be reported for both blank values
105+ assertThat (errors .hasErrors ()).isTrue ();
106+ assertThat (errors .getErrorCount ()).isEqualTo (2 );
107+ assertThat (errors .getFieldError ("map[longEnoughKey1]" )).isNotNull ();
108+ assertThat (errors .getFieldError ("map[longEnoughKey1]" ).getCode ()).isEqualTo ("value.blank" );
109+ assertThat (errors .getFieldError ("map[longEnoughKey2]" )).isNotNull ();
110+ assertThat (errors .getFieldError ("map[longEnoughKey2]" ).getCode ()).isEqualTo ("value.blank" );
111+ }
112+
113+ @ Test
114+ void givenMapWithNullValue_whenValidateIsCalled_thenRejectsWithInvalidTypeError () {
115+ Map <String , Object > mapWithNullValue = new LinkedHashMap <>();
116+ mapWithNullValue .put ("longEnoughKey1" , null ); // Null value (will fail type check first)
117+ mapWithNullValue .put ("longEnoughKey2" , "Valid Value" );
118+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
119+
120+ mapValidator .validate (mapWithNullValue , errors );
121+
122+ assertThat (errors .hasErrors ()).isTrue ();
123+ assertThat (errors .getErrorCount ()).isEqualTo (1 );
124+ assertThat (errors .getFieldError ("map[longEnoughKey1]" )).isNotNull ();
125+ assertThat (errors .getFieldError ("map[longEnoughKey1]" ).getCode ()).isEqualTo ("map.entry.invalidType" );
126+ }
127+
128+ @ Test
129+ void givenMapWithMultipleValidationIssues_whenValidateIsCalled_thenReportsAllErrors () {
130+ Map <Object , Object > mapWithMultipleErrors = new LinkedHashMap <>();
131+ mapWithMultipleErrors .put ("short" , "Valid Value" ); // Short key
132+ mapWithMultipleErrors .put ("longEnoughKey1" , "" ); // Blank value
133+ mapWithMultipleErrors .put (123 , "Value" ); // Invalid key type
134+ mapWithMultipleErrors .put ("longEnoughKey2" , 456 ); // Invalid value type
135+ mapWithMultipleErrors .put ("anotherValidKeyHere" , "Good Value" ); // Valid entry
136+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
137+
138+ mapValidator .validate (mapWithMultipleErrors , errors );
139+
140+ assertThat (errors .hasErrors ()).isTrue ();
141+ assertThat (errors .getErrorCount ()).isEqualTo (4 );
142+
143+ // Check specific errors
144+ assertThat (errors .getFieldError ("map[short]" )).isNotNull ();
145+ assertThat (errors .getFieldError ("map[short]" ).getCode ()).isEqualTo ("key.tooShort" );
146+
147+ assertThat (errors .getFieldError ("map[longEnoughKey1]" )).isNotNull ();
148+ assertThat (errors .getFieldError ("map[longEnoughKey1]" ).getCode ()).isEqualTo ("value.blank" );
149+
150+ assertThat (errors .getFieldError ("map[123]" )).isNotNull ();
151+ assertThat (errors .getFieldError ("map[123]" ).getCode ()).isEqualTo ("map.entry.invalidType" );
152+
153+ assertThat (errors .getFieldError ("map[longEnoughKey2]" )).isNotNull ();
154+ assertThat (errors .getFieldError ("map[longEnoughKey2]" ).getCode ()).isEqualTo ("map.entry.invalidType" );
155+ }
156+
157+ @ Test
158+ void givenEmptyMap_whenValidateIsCalled_thenValidationSucceeds () {
159+ Map <String , String > emptyMap = new HashMap <>();
160+ Errors errors = new MapBindingResult (new HashMap <>(), OBJECT_NAME );
161+
162+ mapValidator .validate (emptyMap , errors );
163+
164+ assertThat (errors .hasErrors ()).isFalse ();
165+ }
166+ }
0 commit comments