1+ package com .bobocode .se ;
2+
3+ import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
4+ import static org .junit .jupiter .api .Assertions .assertEquals ;
5+ import static org .junit .jupiter .api .Assertions .assertThrows ;
6+
7+ import java .lang .reflect .Field ;
8+ import java .util .Arrays ;
9+ import lombok .AllArgsConstructor ;
10+ import lombok .NoArgsConstructor ;
11+ import lombok .SneakyThrows ;
12+ import org .junit .jupiter .api .DisplayName ;
13+ import org .junit .jupiter .api .MethodOrderer .OrderAnnotation ;
14+ import org .junit .jupiter .api .Order ;
15+ import org .junit .jupiter .api .Test ;
16+ import org .junit .jupiter .api .TestMethodOrder ;
17+
18+ @ TestMethodOrder (OrderAnnotation .class )
19+ class RandomFieldComparatorTest {
20+
21+ private final RandomFieldComparator <Account > randomFieldComparator = new RandomFieldComparator <>(Account .class );
22+
23+ @ Test
24+ @ Order (1 )
25+ @ DisplayName ("Constructor throws an exception when parameter is null" )
26+ void classDoesNotApplyNullInConstructor () {
27+ assertThrows (NullPointerException .class , () -> new RandomFieldComparator <>(null ));
28+ }
29+
30+ @ Test
31+ @ Order (2 )
32+ @ SneakyThrows
33+ @ DisplayName ("Constructor throws an exception when the target type has no Comparable fields" )
34+ void constructorThrowsExceptionIfNoComparableFieldsInProvidedType () {
35+ assertThrows (IllegalArgumentException .class , () -> new RandomFieldComparator <>(ClassWithNotComparableField .class ));
36+ }
37+
38+ @ Test
39+ @ Order (3 )
40+ @ DisplayName ("Method 'compare' throws an exception when any parameter is null" )
41+ void compareWhenFirstParameterAreNull () {
42+
43+ assertThrows (NullPointerException .class , () -> randomFieldComparator .compare (null , new Account ()));
44+ assertThrows (NullPointerException .class , () -> randomFieldComparator .compare (new Account (), null ));
45+ }
46+
47+ @ Test
48+ @ Order (4 )
49+ @ DisplayName ("Method 'compare' returns 0 when field values of both objects are null" )
50+ void compareWhenBothFieldValuesIsNull () {
51+ setFieldToCompare ("lastName" , Account .class );
52+ int compareResult = randomFieldComparator .compare (new Account (), new Account ());
53+
54+ assertThat (compareResult ).isZero ();
55+ }
56+
57+ @ Test
58+ @ Order (5 )
59+ @ DisplayName ("Method compare returns positive int when the first field value is null" )
60+ void compareWhenFieldValuesOfFirstObjectIsNull () {
61+ Account emptyAccount = new Account ();
62+ Account account =
new Account (
"Sibma" ,
"LoinKing" ,
"[email protected] " ,
14 );
63+ setFieldToCompare ("email" , Account .class );//set field to compare explicitly as there are int field which has default value 0
64+ int compareResult = randomFieldComparator .compare (emptyAccount , account );
65+
66+ assertThat (compareResult ).isPositive ();
67+ }
68+
69+ @ Test
70+ @ Order (6 )
71+ @ DisplayName ("Method compare returns negative int when the second field value is null" )
72+ void compareWhenFieldValuesOfSecondObjectIsNull () {
73+ Account account =
new Account (
"Mufasa" ,
"LoinKing" ,
"[email protected] " ,
47 );
74+ Account emptyAccount = new Account ();
75+ setFieldToCompare ("firstName" , Account .class );
76+ int compareResult = randomFieldComparator .compare (account , emptyAccount );
77+
78+ assertThat (compareResult ).isNegative ();
79+ }
80+
81+ @ Test
82+ @ Order (7 )
83+ @ SneakyThrows
84+ @ DisplayName ("Method 'compare' returns positive int when the first value is greater" )
85+ void compareWhenFieldValueOfFirstObjectIsGrater () {
86+ var fieldToCompareName = "firstName" ;
87+ Account account1 = new Account ();
88+ Account account2 = new Account ();
89+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
90+ fieldToCompareAccount .setAccessible (true );
91+
92+ fieldToCompareAccount .set (account1 , "Bob" );
93+ fieldToCompareAccount .set (account2 , "Alice" );
94+
95+ setFieldToCompare (fieldToCompareName , Account .class );
96+ int compareResult = randomFieldComparator .compare (account1 , account2 );
97+
98+ assertThat (compareResult ).isPositive ();
99+ }
100+
101+ @ Test
102+ @ Order (8 )
103+ @ SneakyThrows
104+ @ DisplayName ("Method 'compare' returns negative int when the first value is smaller" )
105+ void compareWhenFieldValueOfSecondObjectIsGrater () {
106+ var fieldToCompareName = "firstName" ;
107+ Account account1 = new Account ();
108+ Account account2 = new Account ();
109+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
110+ fieldToCompareAccount .setAccessible (true );
111+
112+ fieldToCompareAccount .set (account1 , "Alice" );
113+ fieldToCompareAccount .set (account2 , "Bob" );
114+
115+ setFieldToCompare (fieldToCompareName , Account .class );
116+ int compareResult = randomFieldComparator .compare (account1 , account2 );
117+
118+ assertThat (compareResult ).isNegative ();
119+ }
120+
121+ @ Test
122+ @ Order (9 )
123+ @ SneakyThrows
124+ @ DisplayName ("Method 'compare' returns zero when the field values are equal" )
125+ void compareWhenFieldValuesOfObjectsAreEqual () {
126+ var fieldToCompareName = "firstName" ;
127+ Account account1 = new Account ();
128+ Account account2 = new Account ();
129+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
130+ fieldToCompareAccount .setAccessible (true );
131+
132+ fieldToCompareAccount .set (account1 , "Carol" );
133+ fieldToCompareAccount .set (account2 , "Carol" );
134+
135+ setFieldToCompare (fieldToCompareName , Account .class );
136+ int compareResult = randomFieldComparator .compare (account1 , account2 );
137+
138+ assertThat (compareResult ).isZero ();
139+ }
140+
141+ @ Test
142+ @ Order (10 )
143+ @ SneakyThrows
144+ @ DisplayName ("Method 'compare' returns positive int when the first primitive value is greater" )
145+ void comparePrimitivesWhenFieldValueOfFirstObjectIsGrater () {
146+ var fieldToCompareName = "age" ;
147+ Account account1 = new Account ();
148+ Account account2 = new Account ();
149+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
150+ fieldToCompareAccount .setAccessible (true );
151+
152+ fieldToCompareAccount .setInt (account1 , 7 );
153+ fieldToCompareAccount .setInt (account2 , 3 );
154+
155+ setFieldToCompare (fieldToCompareName , Account .class );
156+ int compareResult = randomFieldComparator .compare (account1 , account2 );
157+
158+ assertThat (compareResult ).isPositive ();
159+ }
160+
161+ @ Test
162+ @ Order (11 )
163+ @ SneakyThrows
164+ @ DisplayName ("Method 'compare' returns zero when the primitive field values are equal" )
165+ void comparePrimitivesWhenFieldValuesOfObjectsAreEqual () {
166+ var fieldToCompareName = "age" ;
167+ Account account1 = new Account ();
168+ Account account2 = new Account ();
169+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
170+ fieldToCompareAccount .setAccessible (true );
171+
172+ fieldToCompareAccount .setInt (account1 , 15 );
173+ fieldToCompareAccount .setInt (account2 , 15 );
174+
175+ setFieldToCompare (fieldToCompareName , Account .class );
176+ int compareResult = randomFieldComparator .compare (account1 , account2 );
177+
178+ assertThat (compareResult ).isZero ();
179+ }
180+
181+ @ Test
182+ @ Order (12 )
183+ @ SneakyThrows
184+ @ DisplayName ("Method 'compare' returns negative int when the first primitive value is smaller" )
185+ void comparePrimitivesWhenFieldValueOfSecondObjectIsGrater () {
186+ var fieldToCompareName = "age" ;
187+ Account account1 = new Account ();
188+ Account account2 = new Account ();
189+ Field fieldToCompareAccount = account1 .getClass ().getDeclaredField (fieldToCompareName );
190+ fieldToCompareAccount .setAccessible (true );
191+
192+ fieldToCompareAccount .setInt (account1 , 4 );
193+ fieldToCompareAccount .setInt (account2 , 8 );
194+
195+ setFieldToCompare (fieldToCompareName , Account .class );
196+ int compareResult = randomFieldComparator .compare (account1 , account2 );
197+
198+ assertThat (compareResult ).isNegative ();
199+ }
200+
201+ @ Test
202+ @ Order (13 )
203+ @ SneakyThrows
204+ @ DisplayName ("Method 'getComparingFieldName' returns the name of randomly-chosen field to be compared" )
205+ void getComparingFieldName () {
206+ var fieldToCompareName = "lastName" ;
207+ setFieldToCompare (fieldToCompareName , Account .class );
208+
209+ assertEquals (fieldToCompareName , randomFieldComparator .getComparingFieldName ());
210+ }
211+
212+ @ Test
213+ @ Order (14 )
214+ @ SneakyThrows
215+ @ DisplayName ("Method toString is properly overridden" )
216+ void toStringOverriding () {
217+ var expectedString = "Random field comparator of class 'Account' is comparing 'email'" ;
218+ var fieldToCompareName = "email" ;
219+ setFieldToCompare (fieldToCompareName , Account .class );
220+
221+ assertEquals (expectedString , randomFieldComparator .toString ());
222+ }
223+
224+ @ SneakyThrows
225+ private <T > void setFieldToCompare (String fieldName , Class <T > classType ) {
226+ Field fieldToCompare = Arrays .stream (randomFieldComparator .getClass ().getDeclaredFields ())
227+ .filter (f -> f .getType ().equals (Field .class ))
228+ .findAny ()
229+ .orElseThrow ();
230+ fieldToCompare .setAccessible (true );
231+ fieldToCompare .set (randomFieldComparator , classType .getDeclaredField (fieldName ));
232+ }
233+
234+ private static class EmptyClass {
235+
236+ }
237+
238+ @ AllArgsConstructor
239+ private static class ClassWithNotComparableField {
240+
241+ private Object field ;
242+ }
243+
244+ @ NoArgsConstructor
245+ @ AllArgsConstructor
246+ private static class Account {
247+
248+ private String firstName ;
249+ private String lastName ;
250+ private String email ;
251+ private int age ;
252+ }
253+ }
0 commit comments