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.builder;
18  
19  import static org.mockito.Mockito.doThrow;
20  import static org.mockito.Mockito.mock;
21  import static org.mockito.Mockito.verify;
22  import static org.mockito.Mockito.verifyNoInteractions;
23  import static org.mockito.Mockito.verifyNoMoreInteractions;
24  
25  import org.apache.commons.configuration2.event.ConfigurationEvent;
26  import org.apache.commons.configuration2.ex.ConfigurationException;
27  import org.apache.commons.configuration2.io.FileHandler;
28  import org.junit.jupiter.api.BeforeEach;
29  import org.junit.jupiter.api.Test;
30  
31  /**
32   * Test class for {@code AutoSaveListener}.
33   */
34  public class TestAutoSaveListener {
35      /** A mock for the associated builder. */
36      private FileBasedConfigurationBuilder<?> builder;
37  
38      /** The listener to be tested. */
39      private AutoSaveListener listener;
40  
41      /**
42       * Sends a configuration changed notification to the test listener.
43       *
44       * @param before flag whether the event is before the update
45       */
46      private void fireChangeEvent(final boolean before) {
47          listener.onEvent(new ConfigurationEvent(this, ConfigurationEvent.ADD_PROPERTY, "someProperty", "someValue", before));
48      }
49  
50      @BeforeEach
51      public void setUp() throws Exception {
52          builder = mock(FileBasedConfigurationBuilder.class);
53          listener = new AutoSaveListener(builder);
54      }
55  
56      /**
57       * Tests that after a load operation changes on the monitored configuration are detected again.
58       */
59      @Test
60      public void testConfigurationChangedAfterLoading() throws ConfigurationException {
61          final FileHandler handler = new FileHandler();
62          listener.loading(handler);
63          fireChangeEvent(false);
64          listener.loaded(handler);
65          fireChangeEvent(false);
66  
67          verify(builder).save();
68          verifyNoMoreInteractions(builder);
69      }
70  
71      /**
72       * Tests whether a change of the monitored configuration causes a save operation.
73       */
74      @Test
75      public void testConfigurationChangedAutoSave() throws ConfigurationException {
76          fireChangeEvent(false);
77  
78          verify(builder).save();
79          verifyNoMoreInteractions(builder);
80      }
81  
82      /**
83       * Tests whether an exception thrown by the builder's save() method is handled.
84       */
85      @Test
86      public void testConfigurationChangedAutoSaveException() throws ConfigurationException {
87          doThrow(new ConfigurationException()).when(builder).save();
88  
89          fireChangeEvent(false);
90  
91          verify(builder).save();
92          verifyNoMoreInteractions(builder);
93      }
94  
95      /**
96       * Tests whether no auto save is triggered before the change to the monitored configuration actually happens.
97       */
98      @Test
99      public void testConfigurationChangedBeforeUpdateNoSave() {
100         fireChangeEvent(true);
101 
102         verifyNoInteractions(builder);
103     }
104 
105     /**
106      * Tests that updated during load operations do not create an auto save.
107      */
108     @Test
109     public void testConfigurationChangedWhileLoading() {
110         listener.loading(new FileHandler());
111         fireChangeEvent(false);
112 
113         verifyNoInteractions(builder);
114     }
115 
116     /**
117      * Tests whether the file handler can be updated and is correctly initialized.
118      */
119     @Test
120     public void testUpdateFileHandler() {
121         final FileHandler handler = mock(FileHandler.class);
122         final FileHandler handler2 = mock(FileHandler.class);
123 
124         listener.updateFileHandler(handler);
125         listener.updateFileHandler(handler2);
126 
127         verify(handler).addFileHandlerListener(listener);
128         verify(handler).removeFileHandlerListener(listener);
129         verify(handler2).addFileHandlerListener(listener);
130         verifyNoMoreInteractions(builder, handler, handler2);
131     }
132 
133     /**
134      * Tests whether updateFileHandler() can deal with null input. This is used for removing the listener when it is no
135      * longer needed.
136      */
137     @Test
138     public void testUpdateFileHandlerNull() {
139         final FileHandler handler = mock(FileHandler.class);
140 
141         listener.updateFileHandler(handler);
142         listener.updateFileHandler(null);
143 
144         verify(handler).addFileHandlerListener(listener);
145         verify(handler).removeFileHandlerListener(listener);
146         verifyNoMoreInteractions(builder, handler);
147     }
148 }