Index: trunk/test/unit/org/openstreetmap/josm/gui/io/UploadTextComponentValidatorTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/io/UploadTextComponentValidatorTest.java	(revision 18487)
+++ trunk/test/unit/org/openstreetmap/josm/gui/io/UploadTextComponentValidatorTest.java	(revision 18491)
@@ -5,8 +5,16 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import java.util.Arrays;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+
 import javax.swing.JLabel;
 import javax.swing.JTextField;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
@@ -40,3 +48,41 @@
         assertThat(feedback.getText(), containsString("Thank you for providing the data source"));
     }
+
+    static Stream<Arguments> testUploadWithMandatoryTerm() {
+        return Stream.of(Arguments.of("upload.comment.mandatory-terms", "Thank you for providing a changeset comment",
+                    (BiFunction<JTextField, JLabel, ? extends UploadTextComponentValidator>)
+                            UploadTextComponentValidator.UploadCommentValidator::new),
+                Arguments.of("upload.source.mandatory-terms", "Thank you for providing the data source",
+                    (BiFunction<JTextField, JLabel, ? extends UploadTextComponentValidator>)
+                            UploadTextComponentValidator.UploadSourceValidator::new)
+        );
+    }
+
+    /**
+     * Unit test of {@link UploadTextComponentValidator.UploadCommentValidator} and
+     * {@link UploadTextComponentValidator.UploadSourceValidator} with mandatory terms
+     */
+    @BasicPreferences
+    @ParameterizedTest
+    @MethodSource
+    void testUploadWithMandatoryTerm(String confPref, String expectedText,
+            BiFunction<JTextField, JLabel, ? extends UploadTextComponentValidator> validatorSupplier) {
+        Config.getPref().putList(confPref, Arrays.asList("myrequired", "xyz"));
+        JTextField textField = new JTextField("");
+        JLabel feedback = new JLabel();
+
+        validatorSupplier.apply(textField, feedback);
+
+        // A too-short string should fail validation
+        textField.setText("");
+        assertThat(feedback.getText(), containsString("The following required terms are missing: [myrequired, xyz]"));
+
+        // A long enough string without the mandatory terms should claim that the required terms are missing
+        textField.setText("a string long enough but missing the mandatory term");
+        assertThat(feedback.getText(), containsString("The following required terms are missing: [myrequired, xyz]"));
+
+        // A valid string should pass
+        textField.setText("a string long enough with the mandatory term #myrequired #xyz");
+        assertThat(feedback.getText(), containsString(expectedText));
+    }
 }
Index: trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java	(revision 18487)
+++ trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java	(revision 18491)
@@ -57,4 +57,5 @@
             // Disable saving on put, just to avoid overwriting pref files
             pref.enableSaveOnPut(false);
+            pref.resetToDefault();
             Config.setPreferencesInstance(pref);
             Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance());
