001: /*
002: * Copyright 2006-2007, Unitils.org
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.unitils.reflectionassert;
017:
018: import java.lang.reflect.InvocationHandler;
019: import java.lang.reflect.Method;
020: import java.lang.reflect.Proxy;
021: import java.util.Collection;
022:
023: import junit.framework.TestCase;
024:
025: import org.unitils.reflectionassert.ReflectionComparator.Difference;
026:
027: /**
028: * Test class for {@link ReflectionComparator}.
029: *
030: * @author Tim Ducheyne
031: * @author Filip Neven
032: */
033: public class ReflectionComparatorTest extends TestCase {
034:
035: /* Test object */
036: private Objects objectsA;
037:
038: /* Same as A but different instance */
039: private Objects objectsB;
040:
041: /* Same as A and B but different string value for stringValue2 */
042: private Objects objectsDifferentValue;
043:
044: /* Test object containing a null value */
045: private Objects objectsNullValue;
046:
047: /* Test object with inner object */
048: private Objects objectsInnerA;
049:
050: /* Same as innerA but different instance */
051: private Objects objectsInnerB;
052:
053: /* Same as innerA and innerB but different int value for inner intValue2 */
054: private Objects objectsInnerDifferentValue;
055:
056: /* Test object containing a circular dependency to itself */
057: private Objects objectsCircularDependencyA;
058:
059: /* Same as circularDependencyA but different instance */
060: private Objects objectsCircularDependencyB;
061:
062: /* Class under test */
063: private ReflectionComparator reflectionComparator,
064: ignoreDefaultReflectionComparator;
065:
066: /**
067: * Initializes the test fixture.
068: */
069: protected void setUp() throws Exception {
070: super .setUp();
071:
072: objectsA = new Objects("test 1", "test 2", null);
073: objectsB = new Objects("test 1", "test 2", null);
074: objectsDifferentValue = new Objects("test 1", "XXXXXX", null);
075: objectsNullValue = new Objects("test 1", null, null);
076:
077: objectsInnerA = new Objects(null, null, objectsA);
078: objectsInnerB = new Objects(null, null, objectsB);
079: objectsInnerDifferentValue = new Objects(null, null,
080: objectsDifferentValue);
081:
082: objectsCircularDependencyA = new Objects(null, null,
083: new Objects(null, null, new Objects(null, null, null)));
084: objectsCircularDependencyB = new Objects(null, null,
085: new Objects(null, null, new Objects(null, null, null)));
086:
087: // create a circular dependency
088: objectsCircularDependencyA.getInner().getInner().setInner(
089: objectsCircularDependencyA);
090: objectsCircularDependencyB.getInner().getInner().setInner(
091: objectsCircularDependencyB);
092:
093: reflectionComparator = ReflectionComparatorChainFactory.STRICT_COMPARATOR;
094: ignoreDefaultReflectionComparator = ReflectionComparatorChainFactory.IGNOREDEFAULTS_COMPARATOR;
095: }
096:
097: /**
098: * Test for two equal objects.
099: */
100: public void testGetDifference_equals() {
101: Difference result = reflectionComparator.getDifference(
102: objectsA, objectsB);
103: assertNull(result);
104: }
105:
106: /**
107: * * Test for two equal objects as an inner field of an object.
108: */
109: public void testGetDifference_equalsInner() {
110: Difference result = reflectionComparator.getDifference(
111: objectsInnerA, objectsInnerB);
112: assertNull(result);
113: }
114:
115: /**
116: * Test case for 2 equal objects that contain a circular reference. This may not cause an infinite loop.
117: */
118: public void testGetDifference_equalsCircularDependency() {
119: Difference result = reflectionComparator.getDifference(
120: objectsCircularDependencyA, objectsCircularDependencyB);
121: assertNull(result);
122: }
123:
124: /**
125: * Test for two objects that contain different values.
126: */
127: public void testGetDifference_notEqualsDifferentValues() {
128: Difference result = reflectionComparator.getDifference(
129: objectsA, objectsDifferentValue);
130:
131: assertNotNull(result);
132: assertEquals("string2", result.getFieldStack().get(0));
133: assertEquals("test 2", result.getLeftValue());
134: assertEquals("XXXXXX", result.getRightValue());
135: }
136:
137: /**
138: * Test case for 2 objects with a right value null.
139: */
140: public void testGetDifference_notEqualsRightNull() {
141: Difference result = reflectionComparator.getDifference(
142: objectsA, objectsNullValue);
143:
144: assertNotNull(result);
145: assertEquals("string2", result.getFieldStack().get(0));
146: assertEquals("test 2", result.getLeftValue());
147: assertEquals(null, result.getRightValue());
148: }
149:
150: /**
151: * Test case for 2 objects with a left value null.
152: */
153: public void testGetDifference_notEqualsLeftNull() {
154: Difference result = reflectionComparator.getDifference(
155: objectsNullValue, objectsA);
156:
157: assertNotNull(result);
158: assertEquals("string2", result.getFieldStack().get(0));
159: assertEquals(null, result.getLeftValue());
160: assertEquals("test 2", result.getRightValue());
161: }
162:
163: /**
164: * Test for objects with inner objects that contain different values.
165: */
166: public void testGetDifference_notEqualsInnerDifferentValues() {
167: Difference result = reflectionComparator.getDifference(
168: objectsInnerA, objectsInnerDifferentValue);
169:
170: assertNotNull(result);
171: assertEquals("inner", result.getFieldStack().get(0));
172: assertEquals("string2", result.getFieldStack().get(1));
173: assertEquals("test 2", result.getLeftValue());
174: assertEquals("XXXXXX", result.getRightValue());
175: }
176:
177: /**
178: * Test case for a null left-argument.
179: */
180: public void testGetDifference_leftNull() {
181: Difference result = reflectionComparator.getDifference(null,
182: objectsA);
183:
184: assertNotNull(result);
185: assertTrue(result.getFieldStack().isEmpty());
186: assertEquals(null, result.getLeftValue());
187: assertSame(objectsA, result.getRightValue());
188: }
189:
190: /**
191: * Test case for a null right-argument.
192: */
193: public void testGetDifference_rightNull() {
194: Difference result = reflectionComparator.getDifference(
195: objectsA, null);
196:
197: assertNotNull(result);
198: assertTrue(result.getFieldStack().isEmpty());
199: assertSame(objectsA, result.getLeftValue());
200: assertEquals(null, result.getRightValue());
201: }
202:
203: /**
204: * Test case for both null arguments.
205: */
206: public void testGetDifference_null() {
207: Difference result = reflectionComparator.getDifference(null,
208: null);
209: assertNull(result);
210: }
211:
212: /**
213: * Test for two equal objects.
214: */
215: public void testIsEqual() {
216: boolean result = reflectionComparator.isEqual(objectsA,
217: objectsB);
218: assertTrue(result);
219: }
220:
221: /**
222: * Test case for getting the field stack as a string.
223: */
224: public void testGetDifferenceFieldStackAsString() {
225: Difference result = reflectionComparator.getDifference(
226: objectsInnerA, objectsInnerDifferentValue);
227: String differenceFieldString = result.getFieldStackAsString();
228:
229: assertEquals("inner.string2", differenceFieldString);
230: }
231:
232: /**
233: * Test for ignored default left value and to check that the right value is not being evaluated (causing a lazy
234: * loading).
235: */
236: public void testGetDifference_equalsIgnoredDefaultNoLazyLoading() {
237: // create a proxy, that will fail if is accessed
238: Collection<?> collection = (Collection<?>) Proxy
239: .newProxyInstance(getClass().getClassLoader(),
240: new Class[] { Collection.class },
241: new InvocationHandler() {
242: public Object invoke(Object proxy,
243: Method method, Object[] args)
244: throws Throwable {
245: fail("Should not be invoked");
246: return null;
247: }
248: });
249:
250: Difference result = ignoreDefaultReflectionComparator
251: .getDifference(new CollectionWrapper(null),
252: new CollectionWrapper(collection));
253: assertNull(result);
254: }
255:
256: /**
257: * Test class with failing equals.
258: */
259: private class Objects {
260:
261: /* A fist object value */
262: private String string1;
263:
264: /* A second object value */
265: private String string2;
266:
267: /* An inner object */
268: private Objects inner;
269:
270: /**
271: * Creates and initializes the objects instance.
272: *
273: * @param stringValue1 the first object value
274: * @param stringValue2 the second object value
275: * @param inner the inner collection
276: */
277: public Objects(String stringValue1, String stringValue2,
278: Objects inner) {
279: this .string1 = stringValue1;
280: this .string2 = stringValue2;
281: this .inner = inner;
282: }
283:
284: /**
285: * Gets the first object value
286: *
287: * @return the value
288: */
289: public String getString1() {
290: return string1;
291: }
292:
293: /**
294: * Gets the second object value
295: *
296: * @return the value
297: */
298: public String getString2() {
299: return string2;
300: }
301:
302: /**
303: * Gets the inner object
304: *
305: * @return the object
306: */
307: public Objects getInner() {
308: return inner;
309: }
310:
311: /**
312: * Sets the inner object
313: *
314: * @param inner the object
315: */
316: public void setInner(Objects inner) {
317: this .inner = inner;
318: }
319:
320: /**
321: * Always returns false
322: *
323: * @param o the object to compare to
324: */
325: @Override
326: public boolean equals(Object o) {
327: return false;
328: }
329: }
330:
331: /**
332: * Test class with a Collection as field. This is declared as interface so that a proxy can be installed in the
333: * field.
334: */
335: private class CollectionWrapper {
336:
337: /* Collection instance */
338: protected Collection<?> innerCollection;
339:
340: /**
341: * Creates a wrapper for the given collection.
342: *
343: * @param innerCollection The collection
344: */
345: public CollectionWrapper(Collection<?> innerCollection) {
346: this.innerCollection = innerCollection;
347: }
348: }
349:
350: }
|