1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.internal.util.reflection;
6
7import org.junit.Test;
8import org.mockitoutil.TestBase;
9
10import java.lang.reflect.Field;
11import java.util.LinkedList;
12
13import static org.junit.Assert.assertEquals;
14import static org.junit.Assert.assertFalse;
15import static org.assertj.core.api.Assertions.assertThat;
16import static org.mockito.Mockito.*;
17
18@SuppressWarnings("unchecked")
19public class LenientCopyToolTest extends TestBase {
20
21    private LenientCopyTool tool = new LenientCopyTool();
22
23    static class InheritMe {
24        protected String protectedInherited = "protected";
25        private String privateInherited = "private";
26    }
27
28    public static class SomeObject extends InheritMe {
29        @SuppressWarnings("unused")
30        // required because static fields needs to be excluded from copying
31        private static int staticField = -100;
32        private int privateField = -100;
33        private transient int privateTransientField = -100;
34        String defaultField = "-100";
35        protected Object protectedField = new Object();
36        public SomeOtherObject instancePublicField = new SomeOtherObject();
37        final int finalField;
38
39        public SomeObject(int finalField) {
40            this.finalField = finalField;
41        }
42    }
43
44    public static class SomeOtherObject {
45    }
46
47    private SomeObject from = new SomeObject(100);
48    private SomeObject to = mock(SomeObject.class);
49
50    @Test
51    public void shouldShallowCopyBasicFinalField() throws Exception {
52        // given
53        assertEquals(100, from.finalField);
54        assertThat(to.finalField).isNotEqualTo(100);
55
56        // when
57        tool.copyToMock(from, to);
58
59        // then
60        assertEquals(100, to.finalField);
61    }
62
63    @Test
64    public void shouldShallowCopyTransientPrivateFields() throws Exception {
65        // given
66        from.privateTransientField = 1000;
67        assertThat(to.privateTransientField).isNotEqualTo(1000);
68
69        // when
70        tool.copyToMock(from, to);
71
72        // then
73        assertEquals(1000, to.privateTransientField);
74    }
75
76    @Test
77    public void shouldShallowCopyLinkedListIntoMock() throws Exception {
78        // given
79        LinkedList fromList = new LinkedList();
80        LinkedList toList = mock(LinkedList.class);
81
82        // when
83        tool.copyToMock(fromList, toList);
84
85        // then no exception is thrown
86    }
87
88    @Test
89    public void shouldShallowCopyFieldValuesIntoMock() throws Exception {
90        // given
91        from.defaultField = "foo";
92        from.instancePublicField = new SomeOtherObject();
93        from.privateField = 1;
94        from.privateTransientField = 2;
95        from.protectedField = 3;
96
97        assertThat(to.defaultField).isNotEqualTo(from.defaultField);
98        assertThat(to.instancePublicField).isNotEqualTo(from.instancePublicField);
99        assertThat(to.privateField).isNotEqualTo(from.privateField);
100        assertThat(to.privateTransientField).isNotEqualTo(from.privateTransientField);
101        assertThat(to.protectedField).isNotEqualTo(from.protectedField);
102
103        // when
104        tool.copyToMock(from, to);
105
106        // then
107        assertEquals(from.defaultField, to.defaultField);
108        assertEquals(from.instancePublicField, to.instancePublicField);
109        assertEquals(from.privateField, to.privateField);
110        assertEquals(from.privateTransientField, to.privateTransientField);
111        assertEquals(from.protectedField, to.protectedField);
112    }
113
114    @Test
115    public void shouldCopyValuesOfInheritedFields() throws Exception {
116        //given
117        ((InheritMe) from).privateInherited = "foo";
118        ((InheritMe) from).protectedInherited = "bar";
119
120        assertThat(((InheritMe) to).privateInherited).isNotEqualTo(((InheritMe) from).privateInherited);
121
122        //when
123        tool.copyToMock(from, to);
124
125        //then
126        assertEquals(((InheritMe) from).privateInherited, ((InheritMe) to).privateInherited);
127    }
128
129    @Test
130    public void shouldEnableAndThenDisableAccessibility() throws Exception {
131        //given
132        Field privateField = SomeObject.class.getDeclaredField("privateField");
133        assertFalse(privateField.isAccessible());
134
135        //when
136        tool.copyToMock(from, to);
137
138        //then
139        privateField = SomeObject.class.getDeclaredField("privateField");
140        assertFalse(privateField.isAccessible());
141    }
142
143    @Test
144    public void shouldContinueEvenIfThereAreProblemsCopyingSingleFieldValue() throws Exception {
145        //given
146        tool.fieldCopier = mock(FieldCopier.class);
147
148        doNothing().
149        doThrow(new IllegalAccessException()).
150        doNothing().
151        when(tool.fieldCopier).
152        copyValue(anyObject(), anyObject(), any(Field.class));
153
154        //when
155        tool.copyToMock(from, to);
156
157        //then
158        verify(tool.fieldCopier, atLeast(3)).copyValue(any(), any(), any(Field.class));
159    }
160
161    @Test
162    public void shouldBeAbleToCopyFromRealObjectToRealObject() throws Exception {
163
164        // given
165        from.defaultField = "defaultField";
166        from.instancePublicField = new SomeOtherObject();
167        from.privateField = 1;
168        from.privateTransientField = 2;
169        from.protectedField = "protectedField";
170        from.protectedInherited = "protectedInherited";
171        to = new SomeObject(0);
172
173        // when
174        tool.copyToRealObject(from, to);
175
176        // then
177        assertEquals(from.defaultField, to.defaultField);
178        assertEquals(from.instancePublicField, to.instancePublicField);
179        assertEquals(from.privateField, to.privateField);
180        assertEquals(from.privateTransientField, to.privateTransientField);
181        assertEquals(from.protectedField, to.protectedField);
182        assertEquals(from.protectedInherited, to.protectedInherited);
183
184    }
185}
186