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    *     https://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  
41      /** An array with the mocks for the child bean declarations. */
42      private BeanDeclaration[] declarations;
43  
44      /**
45       * Creates a test instance with a number of mock child declarations.
46       *
47       * @return the test instance
48       */
49      private CombinedBeanDeclaration createCombinedDeclaration() {
50          declarations = new BeanDeclaration[3];
51          for (int i = 0; i < declarations.length; i++) {
52              declarations[i] = mock(BeanDeclaration.class);
53          }
54          return new CombinedBeanDeclaration(declarations);
55      }
56  
57      /**
58       * Convenience method for accessing a mock declaration with the given index.
59       *
60       * @param idx the index
61       * @return the corresponding mock child bean declaration
62       */
63      private BeanDeclaration decl(final int idx) {
64          return declarations[idx];
65      }
66  
67      /**
68       * Tests whether the bean class name can be obtained if it is set for one of the child declarations.
69       */
70      @Test
71      void testGetBeanClassNameDefined() {
72          final CombinedBeanDeclaration cd = createCombinedDeclaration();
73  
74          when(decl(0).getBeanClassName()).thenReturn(null);
75          when(decl(1).getBeanClassName()).thenReturn(getClass().getName());
76  
77          assertEquals(getClass().getName(), cd.getBeanClassName());
78  
79          verify(decl(0)).getBeanClassName();
80          verify(decl(1)).getBeanClassName();
81          verifyNoMoreDeclarationInteractions();
82      }
83  
84      /**
85       * Tests getBeanClassName() if none of the child declarations provide a value.
86       */
87      @Test
88      void testGetBeanClassNameUndefined() {
89          final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
90          assertNull(cd.getBeanClassName());
91      }
92  
93      /**
94       * Tests whether the bean factory can be obtained if it is set for one child declarations.
95       */
96      @Test
97      void testGetBeanFactoryNameDefined() {
98          final CombinedBeanDeclaration cd = createCombinedDeclaration();
99          final String name = "someTestBeanFactory";
100 
101         when(decl(0).getBeanFactoryName()).thenReturn(null);
102         when(decl(1).getBeanFactoryName()).thenReturn(name);
103 
104         assertEquals(name, cd.getBeanFactoryName());
105 
106         verify(decl(0)).getBeanFactoryName();
107         verify(decl(1)).getBeanFactoryName();
108         verifyNoMoreDeclarationInteractions();
109     }
110 
111     /**
112      * Tests getBeanFactoryName() if none of the child declarations provide a value.
113      */
114     @Test
115     void testGetBeanFactoryNameUndefined() {
116         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
117         assertNull(cd.getBeanFactoryName());
118     }
119 
120     /**
121      * Tests whether the bean factory parameter can be obtained if it is set for one of the child declarations.
122      */
123     @Test
124     void testGetBeanFactoryParameterDefined() {
125         final CombinedBeanDeclaration cd = createCombinedDeclaration();
126         final Object param = new Object();
127 
128         when(decl(0).getBeanFactoryParameter()).thenReturn(null);
129         when(decl(1).getBeanFactoryParameter()).thenReturn(param);
130 
131         assertSame(param, cd.getBeanFactoryParameter());
132 
133         verify(decl(0)).getBeanFactoryParameter();
134         verify(decl(1)).getBeanFactoryParameter();
135         verifyNoMoreDeclarationInteractions();
136     }
137 
138     /**
139      * Tests getBeanFactoryParameter() if none of the child declarations provide a value.
140      */
141     @Test
142     void testGetBeanFactoryParameterUndefined() {
143         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration();
144         assertNull(cd.getBeanFactoryParameter());
145     }
146 
147     /**
148      * Tests whether a combined map of bean properties can be obtained.
149      */
150     @Test
151     void testGetBeanProperties() {
152         final Map<String, Object> props1 = new HashMap<>();
153         final Map<String, Object> props2 = new HashMap<>();
154         final Map<String, Object> props3 = new HashMap<>();
155         props1.put("param1", "value1");
156         props1.put("param2", "value2");
157         props2.put("param2", "othervalue");
158         props2.put("param3", "value3");
159         props3.put("param1", "differentvalue");
160         props3.put("param4", "value4");
161         final CombinedBeanDeclaration cd = createCombinedDeclaration();
162 
163         when(decl(0).getBeanProperties()).thenReturn(props1);
164         when(decl(1).getBeanProperties()).thenReturn(props2);
165         when(decl(2).getBeanProperties()).thenReturn(props3);
166 
167         final Map<String, Object> props = cd.getBeanProperties();
168 
169         final Map<String, String> expected = new HashMap<>();
170         expected.put("param1", "value1");
171         expected.put("param2", "value2");
172         expected.put("param3", "value3");
173         expected.put("param4", "value4");
174         assertEquals(expected, props);
175 
176         verify(decl(0)).getBeanProperties();
177         verify(decl(1)).getBeanProperties();
178         verify(decl(2)).getBeanProperties();
179         verifyNoMoreDeclarationInteractions();
180     }
181 
182     /**
183      * Tests whether null return values of bean property maps are handled correctly.
184      */
185     @Test
186     void testGetBeanPropertiesNull() {
187         final BeanDeclaration child = mock(BeanDeclaration.class);
188 
189         when(child.getBeanProperties()).thenReturn(null);
190 
191         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration(child);
192         assertEquals(Collections.emptyMap(), cd.getBeanProperties());
193 
194         verify(child).getBeanProperties();
195         verifyNoMoreInteractions(child);
196     }
197 
198     /**
199      * Tests whether constructor arguments can be obtained if one of the child declarations provide this data.
200      */
201     @Test
202     void testGetConstructorArgsDefined() {
203         final CombinedBeanDeclaration cd = createCombinedDeclaration();
204         final Collection<ConstructorArg> args = Arrays.asList(ConstructorArg.forValue(42));
205 
206         when(decl(0).getConstructorArgs()).thenReturn(null);
207         when(decl(1).getConstructorArgs()).thenReturn(args);
208 
209         assertSame(args, cd.getConstructorArgs());
210 
211         verify(decl(0)).getConstructorArgs();
212         verify(decl(1)).getConstructorArgs();
213         verifyNoMoreDeclarationInteractions();
214     }
215 
216     /**
217      * Tests getConstructorArgs() if none of the child declarations provide a value.
218      */
219     @Test
220     void testGetConstructorArgsUndefined() {
221         final CombinedBeanDeclaration cd = createCombinedDeclaration();
222 
223         when(decl(0).getConstructorArgs()).thenReturn(null);
224         when(decl(1).getConstructorArgs()).thenReturn(new ArrayList<>());
225         when(decl(2).getConstructorArgs()).thenReturn(null);
226 
227         assertEquals(Collections.emptyList(), new ArrayList<>(cd.getConstructorArgs()));
228 
229         verify(decl(0)).getConstructorArgs();
230         verify(decl(1)).getConstructorArgs();
231         verify(decl(2)).getConstructorArgs();
232         verifyNoMoreDeclarationInteractions();
233     }
234 
235     /**
236      * Tests whether a combined map of nested bean declarations can be obtained.
237      */
238     @Test
239     void testGetNestedBeanDeclarations() {
240         final Map<String, Object> decls1 = new HashMap<>();
241         final Map<String, Object> decls2 = new HashMap<>();
242         final Map<String, Object> decls3 = new HashMap<>();
243         decls1.put("param1", "value1");
244         decls1.put("param2", "value2");
245         decls2.put("param2", "othervalue");
246         decls2.put("param3", "value3");
247         decls3.put("param1", "differentvalue");
248         decls3.put("param4", "value4");
249         final CombinedBeanDeclaration cd = createCombinedDeclaration();
250 
251         when(decl(0).getNestedBeanDeclarations()).thenReturn(decls1);
252         when(decl(1).getNestedBeanDeclarations()).thenReturn(decls2);
253         when(decl(2).getNestedBeanDeclarations()).thenReturn(decls3);
254 
255         final Map<String, Object> decls = cd.getNestedBeanDeclarations();
256 
257         final Map<String, String> expected = new HashMap<>();
258         expected.put("param1", "value1");
259         expected.put("param2", "value2");
260         expected.put("param3", "value3");
261         expected.put("param4", "value4");
262         assertEquals(expected, decls);
263 
264         verify(decl(0)).getNestedBeanDeclarations();
265         verify(decl(1)).getNestedBeanDeclarations();
266         verify(decl(2)).getNestedBeanDeclarations();
267         verifyNoMoreDeclarationInteractions();
268     }
269 
270     /**
271      * Tests whether null return values of bean declaration maps are handled correctly.
272      */
273     @Test
274     void testGetNestedBeanDeclarationsNull() {
275         final BeanDeclaration child = mock(BeanDeclaration.class);
276 
277         when(child.getNestedBeanDeclarations()).thenReturn(null);
278 
279         final CombinedBeanDeclaration cd = new CombinedBeanDeclaration(child);
280         assertEquals(Collections.emptyMap(), cd.getNestedBeanDeclarations());
281 
282         verify(child).getNestedBeanDeclarations();
283         verifyNoMoreInteractions(child);
284     }
285 
286     /**
287      * Helper method for verifying that no more interactions have been performed on all declarations.
288      */
289     private void verifyNoMoreDeclarationInteractions() {
290         verifyNoMoreInteractions((Object[]) declarations);
291     }
292 }