View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration2.beanutils;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNull;
21  import static org.junit.jupiter.api.Assertions.assertSame;
22  import static org.mockito.Mockito.mock;
23  import static org.mockito.Mockito.verify;
24  import static org.mockito.Mockito.verifyNoMoreInteractions;
25  import static org.mockito.Mockito.when;
26  
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.Collections;
31  import java.util.HashMap;
32  import java.util.Map;
33  
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Test class for {@code CombinedBeanDeclaration}.
38   */
39  public class TestCombinedBeanDeclaration {
40      /** An array with the mocks for the child bean declarations. */
41      private BeanDeclaration[] declarations;
42  
43      /**
44       * Creates a test instance with a number of mock child declarations.
45       *
46       * @return the test instance
47       */
48      private CombinedBeanDeclaration createCombinedDeclaration() {
49          declarations = new BeanDeclaration[3];
50          for (int i = 0; i < declarations.length; i++) {
51              declarations[i] = mock(BeanDeclaration.class);
52          }
53          return new CombinedBeanDeclaration(declarations);
54      }
55  
56      /**
57       * Convenience method for accessing a mock declaration with the given index.
58       *
59       * @param idx the index
60       * @return the corresponding mock child bean declaration
61       */
62      private BeanDeclaration decl(final int idx) {
63          return declarations[idx];
64      }
65  
66      /**
67       * Tests whether the bean class name can be obtained if it is set for one of the child declarations.
68       */
69      @Test
70      public void testGetBeanClassNameDefined() {
71          final CombinedBeanDeclaration cd = createCombinedDeclaration();
72  
73          when(decl(0).getBeanClassName()).thenReturn(null);
74          when(decl(1).getBeanClassName()).thenReturn(getClass().getName());
75  
76          assertEquals(getClass().getName(), cd.getBeanClassName());
77  
78          verify(decl(0)).getBeanClassName();
79          verify(decl(1)).getBeanClassName();
80          verifyNoMoreDeclarationInteractions();
81      }
82  
83      /**
84       * Tests getBeanClassName() if none of the child declarations provide a value.
85       */
86      @Test
87      public void testGetBeanClassNameUndefined() {
88          final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
89          assertNull(cd.getBeanClassName());
90      }
91  
92      /**
93       * Tests whether the bean factory can be obtained if it is set for one child declarations.
94       */
95      @Test
96      public void testGetBeanFactoryNameDefined() {
97          final CombinedBeanDeclaration cd = createCombinedDeclaration();
98          final String name = "someTestBeanFactory";
99  
100         when(decl(0).getBeanFactoryName()).thenReturn(null);
101         when(decl(1).getBeanFactoryName()).thenReturn(name);
102 
103         assertEquals(name, cd.getBeanFactoryName());
104 
105         verify(decl(0)).getBeanFactoryName();
106         verify(decl(1)).getBeanFactoryName();
107         verifyNoMoreDeclarationInteractions();
108     }
109 
110     /**
111      * Tests getBeanFactoryName() if none of the child declarations provide a value.
112      */
113     @Test
114     public void testGetBeanFactoryNameUndefined() {
115         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
116         assertNull(cd.getBeanFactoryName());
117     }
118 
119     /**
120      * Tests whether the bean factory parameter can be obtained if it is set for one of the child declarations.
121      */
122     @Test
123     public void testGetBeanFactoryParameterDefined() {
124         final CombinedBeanDeclaration cd = createCombinedDeclaration();
125         final Object param = new Object();
126 
127         when(decl(0).getBeanFactoryParameter()).thenReturn(null);
128         when(decl(1).getBeanFactoryParameter()).thenReturn(param);
129 
130         assertSame(param, cd.getBeanFactoryParameter());
131 
132         verify(decl(0)).getBeanFactoryParameter();
133         verify(decl(1)).getBeanFactoryParameter();
134         verifyNoMoreDeclarationInteractions();
135     }
136 
137     /**
138      * Tests getBeanFactoryParameter() if none of the child declarations provide a value.
139      */
140     @Test
141     public void testGetBeanFactoryParameterUndefined() {
142         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
143         assertNull(cd.getBeanFactoryParameter());
144     }
145 
146     /**
147      * Tests whether a combined map of bean properties can be obtained.
148      */
149     @Test
150     public void testGetBeanProperties() {
151         final Map<String, Object> props1 = new HashMap<>();
152         final Map<String, Object> props2 = new HashMap<>();
153         final Map<String, Object> props3 = new HashMap<>();
154         props1.put("param1", "value1");
155         props1.put("param2", "value2");
156         props2.put("param2", "othervalue");
157         props2.put("param3", "value3");
158         props3.put("param1", "differentvalue");
159         props3.put("param4", "value4");
160         final CombinedBeanDeclaration cd = createCombinedDeclaration();
161 
162         when(decl(0).getBeanProperties()).thenReturn(props1);
163         when(decl(1).getBeanProperties()).thenReturn(props2);
164         when(decl(2).getBeanProperties()).thenReturn(props3);
165 
166         final Map<String, Object> props = cd.getBeanProperties();
167 
168         final Map<String, String> expected = new HashMap<>();
169         expected.put("param1", "value1");
170         expected.put("param2", "value2");
171         expected.put("param3", "value3");
172         expected.put("param4", "value4");
173         assertEquals(expected, props);
174 
175         verify(decl(0)).getBeanProperties();
176         verify(decl(1)).getBeanProperties();
177         verify(decl(2)).getBeanProperties();
178         verifyNoMoreDeclarationInteractions();
179     }
180 
181     /**
182      * Tests whether null return values of bean property maps are handled correctly.
183      */
184     @Test
185     public void testGetBeanPropertiesNull() {
186         final BeanDeclaration child = mock(BeanDeclaration.class);
187 
188         when(child.getBeanProperties()).thenReturn(null);
189 
190         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration(child);
191         assertEquals(Collections.emptyMap(), cd.getBeanProperties());
192 
193         verify(child).getBeanProperties();
194         verifyNoMoreInteractions(child);
195     }
196 
197     /**
198      * Tests whether constructor arguments can be obtained if one of the child declarations provide this data.
199      */
200     @Test
201     public void testGetConstructorArgsDefined() {
202         final CombinedBeanDeclaration cd = createCombinedDeclaration();
203         final Collection<ConstructorArg> args = Arrays.asList(ConstructorArg.forValue(42));
204 
205         when(decl(0).getConstructorArgs()).thenReturn(null);
206         when(decl(1).getConstructorArgs()).thenReturn(args);
207 
208         assertSame(args, cd.getConstructorArgs());
209 
210         verify(decl(0)).getConstructorArgs();
211         verify(decl(1)).getConstructorArgs();
212         verifyNoMoreDeclarationInteractions();
213     }
214 
215     /**
216      * Tests getConstructorArgs() if none of the child declarations provide a value.
217      */
218     @Test
219     public void testGetConstructorArgsUndefined() {
220         final CombinedBeanDeclaration cd = createCombinedDeclaration();
221 
222         when(decl(0).getConstructorArgs()).thenReturn(null);
223         when(decl(1).getConstructorArgs()).thenReturn(new ArrayList<>());
224         when(decl(2).getConstructorArgs()).thenReturn(null);
225 
226         assertEquals(Collections.emptyList(), new ArrayList<>(cd.getConstructorArgs()));
227 
228         verify(decl(0)).getConstructorArgs();
229         verify(decl(1)).getConstructorArgs();
230         verify(decl(2)).getConstructorArgs();
231         verifyNoMoreDeclarationInteractions();
232     }
233 
234     /**
235      * Tests whether a combined map of nested bean declarations can be obtained.
236      */
237     @Test
238     public void testGetNestedBeanDeclarations() {
239         final Map<String, Object> decls1 = new HashMap<>();
240         final Map<String, Object> decls2 = new HashMap<>();
241         final Map<String, Object> decls3 = new HashMap<>();
242         decls1.put("param1", "value1");
243         decls1.put("param2", "value2");
244         decls2.put("param2", "othervalue");
245         decls2.put("param3", "value3");
246         decls3.put("param1", "differentvalue");
247         decls3.put("param4", "value4");
248         final CombinedBeanDeclaration cd = createCombinedDeclaration();
249 
250         when(decl(0).getNestedBeanDeclarations()).thenReturn(decls1);
251         when(decl(1).getNestedBeanDeclarations()).thenReturn(decls2);
252         when(decl(2).getNestedBeanDeclarations()).thenReturn(decls3);
253 
254         final Map<String, Object> decls = cd.getNestedBeanDeclarations();
255 
256         final Map<String, String> expected = new HashMap<>();
257         expected.put("param1", "value1");
258         expected.put("param2", "value2");
259         expected.put("param3", "value3");
260         expected.put("param4", "value4");
261         assertEquals(expected, decls);
262 
263         verify(decl(0)).getNestedBeanDeclarations();
264         verify(decl(1)).getNestedBeanDeclarations();
265         verify(decl(2)).getNestedBeanDeclarations();
266         verifyNoMoreDeclarationInteractions();
267     }
268 
269     /**
270      * Tests whether null return values of bean declaration maps are handled correctly.
271      */
272     @Test
273     public void testGetNestedBeanDeclarationsNull() {
274         final BeanDeclaration child = mock(BeanDeclaration.class);
275 
276         when(child.getNestedBeanDeclarations()).thenReturn(null);
277 
278         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration(child);
279         assertEquals(Collections.emptyMap(), cd.getNestedBeanDeclarations());
280 
281         verify(child).getNestedBeanDeclarations();
282         verifyNoMoreInteractions(child);
283     }
284 
285     /**
286      * Helper method for verifying that no more interactions have been performed on all declarations.
287      */
288     private void verifyNoMoreDeclarationInteractions() {
289         verifyNoMoreInteractions((Object[]) declarations);
290     }
291 }