1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package com.gargoylesoftware.base.testing;
39
40 import com.gargoylesoftware.base.util.DetailedNullPointerException;
41 import java.util.Date;
42 import junit.framework.AssertionFailedError;
43 import junit.framework.TestCase;
44
45 /***
46 * Tests for EqualsTester
47 *
48 * @version $Revision: 1.9 $
49 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
50 */
51 public class EqualsTesterTest extends TestCase {
52 /***
53 * Create an instance
54 *
55 * @param name Name of the test
56 */
57 public EqualsTesterTest( final String name ) {
58 super( name );
59 }
60
61
62 /***
63 * Test the good case
64 */
65 public void testProperlyImplementedClass() {
66 final ProperlyImplementedEquals a = new ProperlyImplementedEquals( 200 );
67 final ProperlyImplementedEquals b = new ProperlyImplementedEquals( 200 );
68 final ProperlyImplementedEquals c = new ProperlyImplementedEquals( 400 );
69 final ProperlyImplementedEquals d =
70 new ProperlyImplementedEquals( 200 ) {
71 };
72
73 new EqualsTester( a, b, c, d );
74 }
75
76
77 /***
78 * Test various combinations of null parameters
79 */
80 public void testEquals_NullValues() {
81 final Date a = new Date( 200 );
82 final Date b = new Date( 200 );
83 final Date c = new Date( 400 );
84 final Date d = new java.sql.Date( 200 );
85
86 try {
87 new EqualsTester( null, b, c, d );
88 fail( "Expected failure for null A" );
89 }
90 catch( final AssertionFailedError expected ) {
91
92 }
93
94 try {
95 new EqualsTester( a, null, c, d );
96 fail( "Expected failure for null B" );
97 }
98 catch( final AssertionFailedError expected ) {
99
100 }
101
102 try {
103 new EqualsTester( a, b, null, d );
104 fail( "Expected failure for null C" );
105 }
106 catch( final AssertionFailedError expected ) {
107
108 }
109 }
110
111
112 /***
113 * Test passing in null when the class we are testing is final. This should
114 * be legal
115 */
116 public void testNullDForFinalClass() {
117 final EqualChecker equalChecker =
118 new EqualChecker() {
119 public boolean equals( final TestObject object1, final TestObject object2 ) {
120 return object2 != null && object1.value_ == object2.value_;
121 }
122 };
123 final TestObject a = new TestObject( equalChecker, 200 );
124 final TestObject b = new TestObject( equalChecker, 200 );
125 final TestObject c = new TestObject( equalChecker, 400 );
126 final TestObject d = null;
127
128 try {
129 new EqualsTester( a, b, c, d );
130 }
131 catch( final NullPointerException e ) {
132 fail( "EqualsTester should allow null for D when class is final" );
133 }
134 }
135
136
137 /***
138 * Test passing in a null D for a non-final class
139 */
140 public void testNullDForNonFinalClass() {
141 /*** Fake class for testing */
142 class Foo {
143 private boolean state;
144
145 /*** @param b The state */
146 public Foo( final boolean b ) {
147 state = b;
148 }
149
150 /***
151 * @param object The object to compare against
152 * @return true if the objects are equal
153 */
154 public boolean equals( final Object object ) {
155 if( object != null && object.getClass() == this.getClass() ) {
156 return state == ( (Foo)object ).state;
157 }
158 return false;
159 }
160
161 /*** @return the hash code */
162 public int hashCode() {
163 return 2;
164 }
165 }
166
167 final Foo a = new Foo( true );
168 final Foo b = new Foo( true );
169 final Foo c = new Foo( false );
170 final Foo d = null;
171
172 try {
173 new EqualsTester( a, b, c, d );
174 fail( "EqualsTester should not allow null for D when class is not final" );
175 }
176 catch( final DetailedNullPointerException e ) {
177 assertEquals("D", e.getArgumentName());
178 }
179 }
180
181
182 /***
183 * Test passing in a subclass that has a badly implemented equals method
184 */
185 public void testSubclassWithBadEquals() {
186 final Date a = new Date( 200 );
187 final Date b = new Date( 200 );
188 final Date c = new Date( 400 );
189 final Date d =
190 new Date( 200 ) {
191 private static final long serialVersionUID = 1L;
192 public boolean equals( final Object object ) {
193 return true;
194 }
195 public int hashCode() {
196 return 2;
197 }
198 };
199
200 try {
201 new EqualsTester( a, b, c, d );
202 fail( "Class and subclass cannot be equal" );
203 }
204 catch( final AssertionFailedError e ) {
205 assertEquals( "a.equals(d)", e.getMessage() );
206 }
207 }
208
209
210 /***
211 * Test a.equals(a)
212 */
213 public void testEquals_AequalsA() {
214 final EqualChecker equalChecker =
215 new EqualChecker() {
216 public boolean equals( final TestObject object1, final TestObject object2 ) {
217 if( object1 == object2 ) {
218 return false;
219 }
220 else {
221 return object1.value_ == object2.value_;
222 }
223 }
224 };
225
226 final TestObject a = new TestObject( equalChecker, 200 );
227 final TestObject b = new TestObject( equalChecker, 200 );
228 final TestObject c = new TestObject( equalChecker, 400 );
229 final TestObject d = null;
230 try {
231 new EqualsTester( a, b, c, d );
232 fail( "A.equals(A)" );
233 }
234 catch( final AssertionFailedError e ) {
235
236 }
237 }
238
239
240 private static final class TestObject {
241 private final EqualChecker equalChecker_;
242 private final int value_;
243
244
245 /***
246 * Create an instance
247 *
248 * @param value
249 * @param equalChecker
250 */
251 public TestObject( final EqualChecker equalChecker, final int value ) {
252 equalChecker_ = equalChecker;
253 value_ = value;
254 }
255
256 /*** @inheritDoc Object#equals(Object) */
257 public boolean equals( final Object object ) {
258 return equalChecker_.equals( this, (TestObject)object );
259 }
260
261 /*** @inheritDoc Object#hashCode() */
262 public int hashCode() {
263 return value_;
264 }
265 }
266
267
268 private static class EqualChecker {
269 /***
270 * Compare these two objects for equality
271 * @param object1 The first object
272 * @param object2 The second Object
273 * @return True if they are equal.
274 */
275 public boolean equals( final TestObject object1, final TestObject object2 ) {
276 return object1 == object2;
277 }
278 }
279
280
281 private class ProperlyImplementedEquals {
282 private final int value_;
283
284 /*** @param value Some value */
285 public ProperlyImplementedEquals( final int value ) {
286 value_ = value;
287 }
288
289 /*** @inheritDoc Object#equals(Object) */
290 public boolean equals( final Object object ) {
291 if( object != null && this.getClass() == object.getClass() ) {
292 final ProperlyImplementedEquals pie = (ProperlyImplementedEquals)object;
293 return value_ == pie.value_;
294 }
295 return false;
296 }
297
298 /*** @inheritDoc Object#hashCode() */
299 public int hashCode() {
300 return value_;
301 }
302 }
303 }
304