Index: trunk/test/functional/org/openstreetmap/josm/tools/HttpClientTest.java
===================================================================
--- trunk/test/functional/org/openstreetmap/josm/tools/HttpClientTest.java	(revision 18100)
+++ trunk/test/functional/org/openstreetmap/josm/tools/HttpClientTest.java	(revision 18106)
@@ -16,6 +16,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.BufferedReader;
@@ -34,38 +35,33 @@
 import java.util.stream.Collectors;
 
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 import org.openstreetmap.josm.tools.HttpClient.Response;
 
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.http.HttpHeader;
 import com.github.tomakehurst.wiremock.http.HttpHeaders;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
 import com.github.tomakehurst.wiremock.matching.UrlPattern;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * Tests the {@link HttpClient}.
  */
-public class HttpClientTest {
-
-    /**
-     * Setup test
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences().timeout(15000);
-
+@HTTP
+@BasicWiremock
+@BasicPreferences
+@Timeout(15)
+class HttpClientTest {
     /**
      * mocked local http server
      */
-    @Rule
-    public WireMockRule localServer = new WireMockRule(WireMockConfiguration.options().dynamicPort());
+    @BasicWiremock
+    public WireMockServer localServer;
 
     private ProgressMonitor progress;
@@ -91,5 +87,5 @@
      * Setup test.
      */
-    @Before
+    @BeforeEach
     public void setUp() {
         localServer.resetAll();
@@ -105,5 +101,5 @@
      */
     @Test
-    public void testConstructorGetterSetter() throws IOException {
+    void testConstructorGetterSetter() throws IOException {
         final URL localUrl = url("");
         final HttpClient client = HttpClient.create(localUrl);
@@ -127,5 +123,5 @@
      */
     @Test
-    public void testGet() throws IOException {
+    void testGet() throws IOException {
         final UrlPattern pattern = urlEqualTo("/get?foo=bar");
         localServer.stubFor(get(pattern).willReturn(aResponse().withStatusMessage("OK")
@@ -151,5 +147,5 @@
      */
     @Test
-    public void testHeaders() throws IOException {
+    void testHeaders() throws IOException {
         final UrlPattern pattern = urlEqualTo("/headers");
         localServer.stubFor(get(pattern).willReturn(aResponse()));
@@ -166,5 +162,5 @@
      */
     @Test
-    public void testFetchUtf8Content() throws IOException {
+    void testFetchUtf8Content() throws IOException {
         localServer.stubFor(get(urlEqualTo("/encoding/utf8"))
                 .willReturn(aResponse().withBody("∀x∈ℝ: UTF-8 encoded sample plain-text file")));
@@ -181,5 +177,5 @@
      */
     @Test
-    public void testPost() throws IOException {
+    void testPost() throws IOException {
         final UrlPattern pattern = urlEqualTo("/post");
         localServer.stubFor(post(pattern).willReturn(aResponse()));
@@ -200,5 +196,5 @@
      */
     @Test
-    public void testPostZero() throws IOException {
+    void testPostZero() throws IOException {
         final UrlPattern pattern = urlEqualTo("/post");
         localServer.stubFor(post(pattern).willReturn(aResponse()));
@@ -215,5 +211,5 @@
 
     @Test
-    public void testRelativeRedirects() throws IOException {
+    void testRelativeRedirects() throws IOException {
         mockRedirects(false, 3);
         final Response response = connect("/relative-redirect/3");
@@ -223,5 +219,5 @@
 
     @Test
-    public void testAbsoluteRedirects() throws IOException {
+    void testAbsoluteRedirects() throws IOException {
         mockRedirects(true, 3);
         final Response response = connect("/absolute-redirect/3");
@@ -234,8 +230,8 @@
      * @throws IOException if an I/O error occurs
      */
-    @Test(expected = IOException.class)
-    public void testTooMuchRedirects() throws IOException {
+    @Test
+    void testTooMuchRedirects() throws IOException {
         mockRedirects(false, 3);
-        HttpClient.create(url("/relative-redirect/3")).setMaxRedirects(2).connect(progress);
+        assertThrows(IOException.class, () -> HttpClient.create(url("/relative-redirect/3")).setMaxRedirects(2).connect(progress));
     }
 
@@ -245,5 +241,5 @@
      */
     @Test
-    public void testHttp418() throws IOException {
+    void testHttp418() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         final Response response = doTestHttp(418, "I'm a teapot!", "I'm a teapot!",
@@ -257,5 +253,5 @@
      */
     @Test
-    public void testHttp401() throws IOException {
+    void testHttp401() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         doTestHttp(401, "UNAUTHORIZED", null);
@@ -267,5 +263,5 @@
      */
     @Test
-    public void testHttp402() throws IOException {
+    void testHttp402() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         doTestHttp(402, "PAYMENT REQUIRED", "Fuck you, pay me!");
@@ -277,5 +273,5 @@
      */
     @Test
-    public void testHttp403() throws IOException {
+    void testHttp403() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         doTestHttp(403, "FORBIDDEN", null);
@@ -287,5 +283,5 @@
      */
     @Test
-    public void testHttp404() throws IOException {
+    void testHttp404() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         doTestHttp(404, "NOT FOUND", null);
@@ -297,5 +293,5 @@
      */
     @Test
-    public void testHttp500() throws IOException {
+    void testHttp500() throws IOException {
         // https://tools.ietf.org/html/rfc2324
         doTestHttp(500, "INTERNAL SERVER ERROR", null);
@@ -307,5 +303,5 @@
      */
     @Test
-    public void testRequestInTime() throws IOException {
+    void testRequestInTime() throws IOException {
         mockDelay(1);
         final Response response = HttpClient.create(url("/delay/1")).setReadTimeout(2000).connect(progress);
@@ -317,8 +313,8 @@
      * @throws IOException always
      */
-    @Test(expected = IOException.class)
-    public void testTakesTooLong() throws IOException {
+    @Test
+    void testTakesTooLong() throws IOException {
         mockDelay(1);
-        HttpClient.create(url("/delay/1")).setReadTimeout(500).connect(progress);
+        assertThrows(IOException.class, () -> HttpClient.create(url("/delay/1")).setReadTimeout(500).connect(progress));
     }
 
@@ -328,5 +324,5 @@
      */
     @Test
-    public void testGzip() throws IOException {
+    void testGzip() throws IOException {
         localServer.stubFor(get(urlEqualTo("/gzip")).willReturn(aResponse().withBody("foo")));
         final Response response = connect("/gzip");
@@ -341,5 +337,5 @@
      */
     @Test
-    public void testOpenUrlGzip() throws IOException {
+    void testOpenUrlGzip() throws IOException {
         final Path path = Paths.get(TestUtils.getTestDataRoot(), "tracks/tracks.gpx.gz");
         final byte[] gpx = Files.readAllBytes(path);
@@ -361,5 +357,5 @@
      */
     @Test
-    public void testOpenUrlBzip() throws IOException {
+    void testOpenUrlBzip() throws IOException {
         final Path path = Paths.get(TestUtils.getTestDataRoot(), "tracks/tracks.gpx.bz2");
         final byte[] gpx = Files.readAllBytes(path);
@@ -381,5 +377,5 @@
      */
     @Test
-    public void testOpenUrlBzipAccordingToContentDisposition() throws IOException {
+    void testOpenUrlBzipAccordingToContentDisposition() throws IOException {
         final Path path = Paths.get(TestUtils.getTestDataRoot(), "tracks/tracks.gpx.bz2");
         final byte[] gpx = Files.readAllBytes(path);
@@ -402,5 +398,5 @@
      */
     @Test
-    public void testTomcatErrorMessage() {
+    void testTomcatErrorMessage() {
         Matcher m = HttpClient.getTomcatErrorMatcher(
             "<html><head><title>Apache Tomcat/DGFiP - Rapport d''erreur</title><style><!--"+
Index: trunk/test/unit/org/openstreetmap/josm/actions/AddImageryLayerActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/AddImageryLayerActionTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/AddImageryLayerActionTest.java	(revision 18106)
@@ -5,13 +5,11 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.List;
 
-import org.junit.Rule;
-import org.junit.Test;
-import org.openstreetmap.josm.TestUtils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -19,6 +17,8 @@
 import org.openstreetmap.josm.gui.layer.WMSLayer;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -27,17 +27,19 @@
  * Unit tests for class {@link AddImageryLayerAction}.
  */
-public final class AddImageryLayerActionTest {
+@BasicWiremock
+@BasicPreferences
+final class AddImageryLayerActionTest {
     /**
      * We need prefs for this. We need platform for actions and the OSM API for checking blacklist.
      */
-    @Rule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences().fakeAPI();
+    public JOSMTestRules test = new JOSMTestRules().fakeAPI();
 
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
@@ -45,5 +47,5 @@
      */
     @Test
-    public void testEnabledState() {
+    void testEnabledState() {
         assertTrue(new AddImageryLayerAction(new ImageryInfo("foo")).isEnabled());
         assertTrue(new AddImageryLayerAction(new ImageryInfo("foo_tms", "http://bar", "tms", null, null)).isEnabled());
@@ -57,5 +59,5 @@
      */
     @Test
-    public void testActionPerformedEnabledTms() {
+    void testActionPerformedEnabledTms() {
         assertTrue(MainApplication.getLayerManager().getLayersOfType(TMSLayer.class).isEmpty());
         new AddImageryLayerAction(new ImageryInfo("foo_tms", "http://bar", "tms", null, null)).actionPerformed(null);
@@ -69,18 +71,18 @@
      */
     @Test
-    public void testActionPerformedEnabledWms() {
-        wireMockRule.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=1.1.1"))
+    void testActionPerformedEnabledWms() {
+        wireMockServer.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=1.1.1"))
                 .willReturn(aResponse()
                         .withStatus(200)
                         .withHeader("Content-Type", "text/xml")
                         .withBodyFile("imagery/wms-capabilities.xml")));
-        wireMockRule.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities"))
+        wireMockServer.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities"))
                 .willReturn(aResponse()
                         .withStatus(404)));
-        wireMockRule.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=1.3.0"))
+        wireMockServer.stubFor(get(urlEqualTo("/wms?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=1.3.0"))
                 .willReturn(aResponse()
                         .withStatus(404)));
 
-        new AddImageryLayerAction(new ImageryInfo("localhost", wireMockRule.url("/wms?"),
+        new AddImageryLayerAction(new ImageryInfo("localhost", wireMockServer.url("/wms?"),
                 "wms_endpoint", null, null)).actionPerformed(null);
         List<WMSLayer> wmsLayers = MainApplication.getLayerManager().getLayersOfType(WMSLayer.class);
@@ -94,5 +96,5 @@
      */
     @Test
-    public void testActionPerformedDisabled() {
+    void testActionPerformedDisabled() {
         assertTrue(MainApplication.getLayerManager().getLayersOfType(TMSLayer.class).isEmpty());
         try {
Index: trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/AbstractDownloadTaskTestParent.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/AbstractDownloadTaskTestParent.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/AbstractDownloadTaskTestParent.java	(revision 18106)
@@ -5,11 +5,10 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
 
-import org.junit.Rule;
-import org.openstreetmap.josm.TestUtils;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -23,13 +22,13 @@
      * Setup test.
      */
-    @Rule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().https();
+    JOSMTestRules test = new JOSMTestRules().https();
 
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
@@ -53,5 +52,5 @@
      */
     protected final String getRemoteFileUrl() {
-        return wireMockRule.url(getRemoteFile());
+        return wireMockServer.url(getRemoteFile());
     }
 
@@ -60,5 +59,5 @@
      */
     protected final void mockHttp() {
-        wireMockRule.stubFor(get(urlEqualTo("/" + getRemoteFile()))
+        wireMockServer.stubFor(get(urlEqualTo("/" + getRemoteFile()))
                 .willReturn(aResponse()
                     .withStatus(200)
Index: trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTaskTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTaskTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTaskTest.java	(revision 18106)
@@ -2,17 +2,19 @@
 package org.openstreetmap.josm.actions.downloadtasks;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.concurrent.ExecutionException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
 /**
  * Unit tests for class {@link DownloadGpsTask}.
  */
-public class DownloadGpsTaskTest extends AbstractDownloadTaskTestParent {
+@BasicWiremock
+class DownloadGpsTaskTest extends AbstractDownloadTaskTestParent {
 
     /**
@@ -20,5 +22,5 @@
      */
     @Test
-    public void testAcceptsURL() {
+    void testAcceptsURL() {
         DownloadGpsTask task = new DownloadGpsTask();
         assertFalse(task.acceptsUrl(null));
@@ -42,5 +44,5 @@
      */
     @Test
-    public void testDownloadExternalFile() throws InterruptedException, ExecutionException {
+    void testDownloadExternalFile() throws InterruptedException, ExecutionException {
         mockHttp();
         DownloadGpsTask task = new DownloadGpsTask();
Index: trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java	(revision 18106)
@@ -2,17 +2,19 @@
 package org.openstreetmap.josm.actions.downloadtasks;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.concurrent.ExecutionException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.data.osm.NoteData;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
 /**
  * Unit tests for class {@link DownloadNotesTask}.
  */
-public class DownloadNotesTaskTest extends AbstractDownloadTaskTestParent {
+@BasicWiremock
+class DownloadNotesTaskTest extends AbstractDownloadTaskTestParent {
 
     /**
@@ -20,5 +22,5 @@
      */
     @Test
-    public void testAcceptsURL() {
+    void testAcceptsURL() {
         DownloadNotesTask task = new DownloadNotesTask();
         assertFalse(task.acceptsUrl(null));
@@ -37,5 +39,5 @@
      */
     @Test
-    public void testDownloadExternalFile() throws InterruptedException, ExecutionException {
+    void testDownloadExternalFile() throws InterruptedException, ExecutionException {
         mockHttp();
         DownloadNotesTask task = new DownloadNotesTask();
Index: trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskTest.java	(revision 18106)
@@ -2,17 +2,19 @@
 package org.openstreetmap.josm.actions.downloadtasks;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.concurrent.ExecutionException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
 /**
  * Unit tests for class {@link DownloadOsmTask}.
  */
-public class DownloadOsmTaskTest extends AbstractDownloadTaskTestParent {
+@BasicWiremock
+class DownloadOsmTaskTest extends AbstractDownloadTaskTestParent {
 
     /**
@@ -20,5 +22,5 @@
      */
     @Test
-    public void testAcceptsURL() {
+    void testAcceptsURL() {
         DownloadOsmTask task = new DownloadOsmTask();
         assertFalse(task.acceptsUrl(null));
@@ -39,5 +41,5 @@
      */
     @Test
-    public void testDownloadExternalFile() throws InterruptedException, ExecutionException {
+    void testDownloadExternalFile() throws InterruptedException, ExecutionException {
         mockHttp();
         DownloadOsmTask task = new DownloadOsmTask();
Index: trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PluginDownloadTaskTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PluginDownloadTaskTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PluginDownloadTaskTest.java	(revision 18106)
@@ -2,7 +2,7 @@
 package org.openstreetmap.josm.actions.downloadtasks;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
@@ -12,6 +12,6 @@
 import java.util.Collections;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.Preferences;
@@ -20,4 +20,6 @@
 import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -27,5 +29,7 @@
  * Unit tests for class {@link PluginDownloadTask}.
  */
-public class PluginDownloadTaskTest extends AbstractDownloadTaskTestParent {
+@BasicWiremock
+@BasicPreferences
+class PluginDownloadTaskTest extends AbstractDownloadTaskTestParent {
     protected String pluginPath;
 
@@ -33,9 +37,9 @@
      * Setup test.
      */
-    @Rule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     public JOSMTestRules testRule = new JOSMTestRules().https().assumeRevision(
         "Revision: 8000\n"
-    ).preferences();
+    );
 
     @Override
@@ -55,5 +59,5 @@
      */
     @Test
-    public void testUpdatePluginValid() throws Exception {
+    void testUpdatePluginValid() throws Exception {
         this.pluginPath = "plugin/dummy_plugin.v31772.jar";
         this.mockHttp();
@@ -97,5 +101,5 @@
      */
     @Test
-    public void testUpdatePluginCorrupt() throws Exception {
+    void testUpdatePluginCorrupt() throws Exception {
         this.pluginPath = "plugin/corrupted_plugin.jar";
         this.mockHttp();
Index: trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java	(revision 18106)
@@ -10,8 +10,8 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.status;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
@@ -23,30 +23,30 @@
 import org.apache.commons.jcs3.access.behavior.ICacheAccess;
 import org.apache.commons.jcs3.engine.behavior.ICacheElement;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.cache.ICachedLoaderListener.LoadResult;
 import org.openstreetmap.josm.data.imagery.TileJobOptions;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 import org.openstreetmap.josm.tools.Logging;
 
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.matching.UrlPattern;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * Unit tests for class {@link JCSCachedTileLoaderJob}.
  */
-public class JCSCachedTileLoaderJobTest {
+@BasicWiremock
+@BasicPreferences
+@Timeout(20)
+class JCSCachedTileLoaderJobTest {
 
     /**
      * mocked tile server
      */
-    @Rule
-    public WireMockRule tileServer = new WireMockRule(WireMockConfiguration.options()
-            .dynamicPort());
+    @BasicWiremock
+    WireMockServer tileServer;
 
     private static class TestCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, CacheEntry> {
@@ -104,16 +104,9 @@
 
     /**
-     * Setup test.
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences().timeout(20_000);
-
-    /**
      * Always clear cache before tests
      * @throws Exception when clearing fails
      */
-    @Before
-    public void clearCache() throws Exception {
+    @BeforeEach
+    void clearCache() throws Exception {
         getCache().clear();
     }
@@ -125,5 +118,5 @@
      */
     @Test
-    public void testStatusCodes() throws IOException, InterruptedException {
+    void testStatusCodes() throws IOException, InterruptedException {
         doTestStatusCode(200);
         doTestStatusCode(401);
@@ -142,5 +135,5 @@
      */
     @Test
-    public void testUnknownHost() throws IOException {
+    void testUnknownHost() throws IOException {
         String key = "key_unknown_host";
         TestCachedTileLoaderJob job = new TestCachedTileLoaderJob("http://unkownhost.unkownhost/unkown", key);
@@ -193,5 +186,5 @@
      */
     @Test
-    public void testNoRequestMadeWhenEntryInCache() throws IOException {
+    void testNoRequestMadeWhenEntryInCache() throws IOException {
         ICacheAccess<String, CacheEntry> cache = getCache();
         long expires = TimeUnit.DAYS.toMillis(1);
@@ -214,5 +207,5 @@
      */
     @Test
-    public void testRequestMadeWhenEntryInCacheAndForce() throws IOException {
+    void testRequestMadeWhenEntryInCacheAndForce() throws IOException {
         ICacheAccess<String, CacheEntry> cache = getCache();
         long expires = TimeUnit.DAYS.toMillis(1);
@@ -236,5 +229,5 @@
      */
     @Test
-    public void testSettingMinimumExpiryWhenNoExpires() throws IOException {
+    void testSettingMinimumExpiryWhenNoExpires() throws IOException {
         long testStart = System.currentTimeMillis();
         tileServer.stubFor(get(urlEqualTo("/test")).willReturn(aResponse().withBody("mock entry")));
@@ -244,13 +237,13 @@
         tileServer.verify(1, getRequestedFor(urlEqualTo("/test")));
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME + " (DEFAULT_EXPIRE_TIME)",
-                listener.attributes.getExpirationTime() >= testStart + JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME);
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME + " (DEFAULT_EXPIRE_TIME)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME
+        assertTrue(listener.attributes.getExpirationTime() >= testStart + JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME,
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME + " (DEFAULT_EXPIRE_TIME)");
+
+        assertTrue(listener.attributes.getExpirationTime() <= System.currentTimeMillis() + JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME,
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME + " (DEFAULT_EXPIRE_TIME)"
                 );
 
@@ -264,5 +257,5 @@
      */
     @Test
-    public void testSettingExpireByMaxAge() throws IOException {
+    void testSettingExpireByMaxAge() throws IOException {
         long testStart = System.currentTimeMillis();
         long expires = TimeUnit.DAYS.toSeconds(1);
@@ -278,14 +271,15 @@
         tileServer.verify(1, getRequestedFor(urlEqualTo("/test")));
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                TimeUnit.SECONDS.toMillis(expires) + " (max-age)",
-                listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(expires));
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                TimeUnit.SECONDS.toMillis(expires) + " (max-age)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expires)
-                );
+        assertTrue(listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(expires),
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        TimeUnit.SECONDS.toMillis(expires) + " (max-age)");
+
+        assertTrue(
+                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expires),
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        TimeUnit.SECONDS.toMillis(expires) + " (max-age)"
+                        );
 
         assertArrayEquals("mock entry".getBytes(StandardCharsets.UTF_8), listener.data);
@@ -298,5 +292,5 @@
      */
     @Test
-    public void testSettingMinimumExpiryByMinimumExpiryTimeLessThanDefault() throws IOException {
+    void testSettingMinimumExpiryByMinimumExpiryTimeLessThanDefault() throws IOException {
         long testStart = System.currentTimeMillis();
         int minimumExpiryTimeSeconds = (int) (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2);
@@ -310,14 +304,16 @@
 
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)",
-                listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds));
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds)
-                );
+        assertTrue(
+                listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds),
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)");
+
+        assertTrue(
+                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds),
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)"
+                        );
     }
 
@@ -329,5 +325,5 @@
 
     @Test
-    public void testSettingMinimumExpiryByMinimumExpiryTimeGreaterThanDefault() throws IOException {
+    void testSettingMinimumExpiryByMinimumExpiryTimeGreaterThanDefault() throws IOException {
         long testStart = System.currentTimeMillis();
         int minimumExpiryTimeSeconds = (int) (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME * 2);
@@ -341,14 +337,16 @@
 
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)",
-                listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds));
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds)
-                );
+        assertTrue(
+                listener.attributes.getExpirationTime() >= testStart + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds),
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)");
+
+        assertTrue(
+                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds),
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        TimeUnit.SECONDS.toMillis(minimumExpiryTimeSeconds) + " (minimumExpireTime)"
+                        );
     }
 
@@ -365,5 +363,5 @@
 
     @Test
-    public void testCacheControlVsExpires() throws IOException {
+    void testCacheControlVsExpires() throws IOException {
         long testStart = System.currentTimeMillis();
         int minimumExpiryTimeSeconds = 0;
@@ -390,14 +388,15 @@
 
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Expires header)",
-                listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10));
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: max-age=)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2)
-                );
+        assertTrue(
+                listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10),
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Expires header)");
+
+        assertTrue(listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2),
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: max-age=)"
+                        );
     }
 
@@ -410,5 +409,5 @@
      */
     @Test
-    public void testMaxAgeVsSMaxAge() throws IOException {
+    void testMaxAgeVsSMaxAge() throws IOException {
         long testStart = System.currentTimeMillis();
         int minimumExpiryTimeSeconds = 0;
@@ -435,14 +434,15 @@
         assertArrayEquals("mock entry".getBytes(StandardCharsets.UTF_8), listener.data);
 
-        assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
-                (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Cache-Control: max-age)",
-                listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10));
-
-        assertTrue("Cache entry expiration is " +
-                (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
-                " which is not less than " +
-                (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: s-max-age)",
-                listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2)
-                );
+        assertTrue(
+                listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10),
+                "Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " +
+                        (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Cache-Control: max-age)");
+
+        assertTrue(listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2),
+                "Cache entry expiration is " +
+                        (listener.attributes.getExpirationTime() - System.currentTimeMillis()) +
+                        " which is not less than " +
+                        (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: s-max-age)"
+                        );
     }
 
@@ -452,5 +452,5 @@
      */
     @Test
-    public void testCheckUsingHead() throws IOException {
+    void testCheckUsingHead() throws IOException {
         ICacheAccess<String, CacheEntry> cache = getCache();
         long expires = TimeUnit.DAYS.toMillis(1);
Index: trunk/test/unit/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJobTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJobTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJobTest.java	(revision 18106)
@@ -2,7 +2,7 @@
 package org.openstreetmap.josm.data.imagery;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
@@ -17,7 +17,6 @@
 
 import org.apache.commons.jcs3.access.behavior.ICacheAccess;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.gui.jmapviewer.Tile;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
@@ -27,35 +26,26 @@
 import org.openstreetmap.josm.data.cache.CacheEntryAttributes;
 import org.openstreetmap.josm.data.cache.JCSCacheManager;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
 
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * Unit tests for class {@link TMSCachedTileLoaderJob}.
  */
-public class TMSCachedTileLoaderJobTest {
-
-    /**
-     * Setup tests
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences();
-
+@BasicWiremock
+@BasicPreferences
+class TMSCachedTileLoaderJobTest {
     /**
      * mocked tile server
      */
-    @Rule
-    public WireMockRule tileServer = new WireMockRule(WireMockConfiguration.options()
-            .dynamicPort());
-
-    @Before
-    public void clearCache() throws Exception {
+    @BasicWiremock
+    WireMockServer tileServer;
+
+    @BeforeEach
+    void clearCache() throws Exception {
         getCache().clear();
     }
@@ -145,5 +135,5 @@
      */
     @Test
-    public void testServiceExceptionPattern() {
+    void testServiceExceptionPattern() {
         testServiceException("missing parameters ['version', 'format']",
                 "<?xml version=\"1.0\"?>\n" +
@@ -167,5 +157,5 @@
      */
     @Test
-    public void testCdataPattern() {
+    void testCdataPattern() {
         testCdata("received unsuitable wms request: no <grid> with suitable srs found for layer capitais",
                 "<![CDATA[\r\n" +
@@ -178,5 +168,5 @@
      */
     @Test
-    public void testJsonPattern() {
+    void testJsonPattern() {
         testJson("Tile does not exist",
                 "{\"message\":\"Tile does not exist\"}");
@@ -197,5 +187,5 @@
     private static void test(Pattern pattern, String expected, String text) {
         Matcher m = pattern.matcher(text);
-        assertTrue(text, m.matches());
+        assertTrue(m.matches(), text);
         assertEquals(expected, Utils.strip(m.group(1)));
     }
@@ -227,5 +217,5 @@
      */
     @Test
-    public void testNoCacheHeaders() throws IOException {
+    void testNoCacheHeaders() throws IOException {
         long testStart = System.currentTimeMillis();
         tileServer.stubFor(
@@ -250,5 +240,5 @@
      */
     @Test
-    public void testNoCacheHeadersMinimumExpires() throws IOException {
+    void testNoCacheHeadersMinimumExpires() throws IOException {
         noCacheHeadersMinimumExpires((int) TimeUnit.MILLISECONDS.toSeconds(TMSCachedTileLoaderJob.MINIMUM_EXPIRES.get() * 2));
     }
@@ -261,5 +251,5 @@
 
     @Test
-    public void testNoCacheHeadersMinimumExpiresLargerThanMaximum() throws IOException {
+    void testNoCacheHeadersMinimumExpiresLargerThanMaximum() throws IOException {
         noCacheHeadersMinimumExpires((int) TimeUnit.MILLISECONDS.toSeconds(TMSCachedTileLoaderJob.MAXIMUM_EXPIRES.get() * 2));
     }
@@ -287,5 +277,5 @@
      */
     @Test
-    public void testShortExpire() throws IOException {
+    void testShortExpire() throws IOException {
         long testStart = System.currentTimeMillis();
         long expires = TMSCachedTileLoaderJob.MINIMUM_EXPIRES.get() / 2;
@@ -307,21 +297,17 @@
 
     private void assertExpirationAtLeast(long duration, TestCachedTileLoaderJob job) {
-        assertTrue(
-                "Expiration time shorter by " +
-                        -1 * (job.getAttributes().getExpirationTime() - duration) +
-                        " than expected",
-                job.getAttributes().getExpirationTime() >= duration);
+        assertTrue(job.getAttributes().getExpirationTime() >= duration, "Expiration time shorter by " +
+                                -1 * (job.getAttributes().getExpirationTime() - duration) +
+                                " than expected");
     }
 
     private void assertExpirationAtMost(long duration, TestCachedTileLoaderJob job) {
-        assertTrue(
-                "Expiration time longer by " +
-                        (job.getAttributes().getExpirationTime() - duration) +
-                        " than expected",
-                job.getAttributes().getExpirationTime() <= duration);
-    }
-
-    @Test
-    public void testLongExpire() throws IOException {
+        assertTrue(job.getAttributes().getExpirationTime() <= duration, "Expiration time longer by " +
+                                (job.getAttributes().getExpirationTime() - duration) +
+                                " than expected");
+    }
+
+    @Test
+    void testLongExpire() throws IOException {
         long testStart = System.currentTimeMillis();
         long expires = TMSCachedTileLoaderJob.MAXIMUM_EXPIRES.get() * 2;
@@ -343,4 +329,3 @@
         assertArrayEquals("mock entry".getBytes(StandardCharsets.UTF_8), job.get().getContent());
     }
-
 }
Index: trunk/test/unit/org/openstreetmap/josm/data/imagery/WMSEndpointTileSourceTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/imagery/WMSEndpointTileSourceTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/data/imagery/WMSEndpointTileSourceTest.java	(revision 18106)
@@ -2,6 +2,6 @@
 package org.openstreetmap.josm.data.imagery;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.nio.file.Files;
@@ -9,6 +9,6 @@
 import java.util.Arrays;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
@@ -17,25 +17,25 @@
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
-public class WMSEndpointTileSourceTest {
+@BasicWiremock
+class WMSEndpointTileSourceTest {
     /**
      * Setup test
      */
-    @Rule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     public JOSMTestRules test = new JOSMTestRules().projection();
 
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public WireMockRule tileServer = new WireMockRule(WireMockConfiguration.options().dynamicPort());
+    @BasicWiremock
+    WireMockServer tileServer;
 
     @Test
-    public void testDefaultLayerSetInMaps() throws Exception {
+    void testDefaultLayerSetInMaps() throws Exception {
 
         tileServer.stubFor(
@@ -87,5 +87,5 @@
 
     @Test
-    public void testCustomHeaders() throws Exception {
+    void testCustomHeaders() throws Exception {
         tileServer.stubFor(
                 WireMock.get(WireMock.urlEqualTo("/capabilities?SERVICE=WMS&REQUEST=GetCapabilities"))
Index: trunk/test/unit/org/openstreetmap/josm/data/imagery/WMTSTileSourceTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/imagery/WMTSTileSourceTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/data/imagery/WMTSTileSourceTest.java	(revision 18106)
@@ -2,6 +2,6 @@
 package org.openstreetmap.josm.data.imagery;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
@@ -15,8 +15,7 @@
 import java.util.concurrent.TimeUnit;
 
-import org.junit.ClassRule;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.gui.jmapviewer.TileXY;
 import org.openstreetmap.gui.jmapviewer.tilesources.TemplatedTMSTileSource;
@@ -30,8 +29,9 @@
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
-
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -40,16 +40,17 @@
  * Unit tests for class {@link WMTSTileSource}.
  */
-public class WMTSTileSourceTest {
+@BasicWiremock
+@BasicPreferences
+class WMTSTileSourceTest {
 
     /**
      * Setup test.
      */
-    @ClassRule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public static JOSMTestRules test = new JOSMTestRules().preferences().projection().timeout((int) TimeUnit.MINUTES.toMillis(5));
-
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public WireMockRule tileServer = new WireMockRule(WireMockConfiguration.options().dynamicPort());
+    public static JOSMTestRules test = new JOSMTestRules().projection().timeout((int) TimeUnit.MINUTES.toMillis(5));
+
+    @BasicWiremock
+    WireMockServer tileServer;
 
     private final ImageryInfo testImageryTMS = new ImageryInfo("test imagery", "http://localhost", "tms", null, null);
@@ -86,5 +87,5 @@
 
     @Test
-    public void testPseudoMercator() throws IOException, WMTSGetCapabilitiesException {
+    void testPseudoMercator() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryPSEUDO_MERCATOR);
@@ -107,14 +108,14 @@
         verifyMercatorTile(testSource, 2 << 9 - 1, 2 << 8 - 1, 10);
 
-        assertEquals("TileXMax", 1, testSource.getTileXMax(0));
-        assertEquals("TileYMax", 1, testSource.getTileYMax(0));
-        assertEquals("TileXMax", 2, testSource.getTileXMax(1));
-        assertEquals("TileYMax", 2, testSource.getTileYMax(1));
-        assertEquals("TileXMax", 4, testSource.getTileXMax(2));
-        assertEquals("TileYMax", 4, testSource.getTileYMax(2));
-    }
-
-    @Test
-    public void testWALLONIE() throws IOException, WMTSGetCapabilitiesException {
+        assertEquals(1, testSource.getTileXMax(0), "TileXMax");
+        assertEquals(1, testSource.getTileYMax(0), "TileYMax");
+        assertEquals(2, testSource.getTileXMax(1), "TileXMax");
+        assertEquals(2, testSource.getTileYMax(1), "TileYMax");
+        assertEquals(4, testSource.getTileXMax(2), "TileXMax");
+        assertEquals(4, testSource.getTileYMax(2), "TileYMax");
+    }
+
+    @Test
+    void testWALLONIE() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:31370"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryWALLONIE);
@@ -135,6 +136,6 @@
 
     @Test
-    @Ignore("disable this test, needs further working") // XXX
-    public void testWALLONIENoMatrixDimension() throws IOException, WMTSGetCapabilitiesException {
+    @Disabled("disable this test, needs further working") // XXX
+    void testWALLONIENoMatrixDimension() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:31370"));
         WMTSTileSource testSource = new WMTSTileSource(getImagery("test/data/wmts/WMTSCapabilities-Wallonie-nomatrixdimension.xml"));
@@ -152,13 +153,13 @@
     private void verifyBounds(Bounds bounds, WMTSTileSource testSource, int z, int x, int y) {
         LatLon ret = CoordinateConversion.coorToLL(testSource.tileXYToLatLon(x, y, z));
-        assertTrue(ret.toDisplayString() + " doesn't lie within: " + bounds.toString(), bounds.contains(ret));
+        assertTrue(bounds.contains(ret), ret.toDisplayString() + " doesn't lie within: " + bounds);
         int tileXmax = testSource.getTileXMax(z);
         int tileYmax = testSource.getTileYMax(z);
-        assertTrue("tile x: " + x + " is greater than allowed max: " + tileXmax, tileXmax >= x);
-        assertTrue("tile y: " + y + " is greater than allowed max: " + tileYmax, tileYmax >= y);
-    }
-
-    @Test
-    public void testWIEN() throws IOException, WMTSGetCapabilitiesException {
+        assertTrue(tileXmax >= x, "tile x: " + x + " is greater than allowed max: " + tileXmax);
+        assertTrue(tileYmax >= y, "tile y: " + y + " is greater than allowed max: " + tileYmax);
+    }
+
+    @Test
+    void testWIEN() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryWIEN);
@@ -195,12 +196,12 @@
         int result = testSource.getTileXMax(zoom);
         int expected = verifier.getTileXMax(zoom + zoomOffset);
-        assertTrue("TileXMax expected: " + expected + " got: " + result, Math.abs(result - expected) < 5);
+        assertTrue(Math.abs(result - expected) < 5, "TileXMax expected: " + expected + " got: " + result);
         result = testSource.getTileYMax(zoom);
         expected = verifier.getTileYMax(zoom + zoomOffset);
-        assertTrue("TileYMax expected: " + expected + " got: " + result, Math.abs(result - expected) < 5);
-    }
-
-    @Test
-    public void testGeoportalTOPOPL() throws IOException, WMTSGetCapabilitiesException {
+        assertTrue(Math.abs(result - expected) < 5, "TileYMax expected: " + expected + " got: " + result);
+    }
+
+    @Test
+    void testGeoportalTOPOPL() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:4326"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryTOPO_PL);
@@ -210,10 +211,10 @@
         verifyTile(new LatLon(51.13231917844218, 16.867680821557823), testSource, 1, 1, 1);
 
-        assertEquals("TileXMax", 2, testSource.getTileXMax(0));
-        assertEquals("TileYMax", 1, testSource.getTileYMax(0));
-        assertEquals("TileXMax", 3, testSource.getTileXMax(1));
-        assertEquals("TileYMax", 2, testSource.getTileYMax(1));
-        assertEquals("TileXMax", 6, testSource.getTileXMax(2));
-        assertEquals("TileYMax", 4, testSource.getTileYMax(2));
+        assertEquals(2, testSource.getTileXMax(0), "TileXMax");
+        assertEquals(1, testSource.getTileYMax(0), "TileYMax");
+        assertEquals(3, testSource.getTileXMax(1), "TileXMax");
+        assertEquals(2, testSource.getTileYMax(1), "TileYMax");
+        assertEquals(6, testSource.getTileXMax(2), "TileXMax");
+        assertEquals(4, testSource.getTileYMax(2), "TileYMax");
         assertEquals(
                 "http://mapy.geoportal.gov.pl/wss/service/WMTS/guest/wmts/TOPO?SERVICE=WMTS&REQUEST=GetTile&"
@@ -224,5 +225,5 @@
 
     @Test
-    public void testGeoportalORTOPL4326() throws IOException, WMTSGetCapabilitiesException {
+    void testGeoportalORTOPL4326() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:4326"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryORTO_PL);
@@ -233,5 +234,5 @@
 
     @Test
-    public void testGeoportalORTOPL2180() throws IOException, WMTSGetCapabilitiesException {
+    void testGeoportalORTOPL2180() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:2180"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryORTO_PL);
@@ -243,5 +244,5 @@
 
     @Test
-    public void testTicket12168() throws IOException, WMTSGetCapabilitiesException {
+    void testTicket12168() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testImagery12168);
@@ -253,5 +254,5 @@
 
     @Test
-    public void testProjectionWithENUAxis() throws IOException, WMTSGetCapabilitiesException {
+    void testProjectionWithENUAxis() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3346"));
         WMTSTileSource testSource = new WMTSTileSource(testImageryORT2LT);
@@ -267,5 +268,5 @@
 
     @Test
-    public void testTwoTileSetsForOneProjection() throws Exception {
+    void testTwoTileSetsForOneProjection() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         ImageryInfo ontario = getImagery(TestUtils.getTestDataRoot() + "wmts/WMTSCapabilities-Ontario.xml");
@@ -284,5 +285,5 @@
 
     @Test
-    public void testTwoTileSetsForOneProjectionSecondLayer() throws Exception {
+    void testTwoTileSetsForOneProjectionSecondLayer() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         ImageryInfo ontario = getImagery(TestUtils.getTestDataRoot() + "wmts/WMTSCapabilities-Ontario.xml");
@@ -301,5 +302,5 @@
 
     @Test
-    public void testManyLayersScrollbars() throws Exception {
+    void testManyLayersScrollbars() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testLotsOfLayers);
@@ -308,5 +309,5 @@
 
     @Test
-    public void testParserForDuplicateTags() throws Exception {
+    void testParserForDuplicateTags() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testDuplicateTags);
@@ -320,5 +321,5 @@
 
     @Test
-    public void testParserForMissingStyleIdentifier() throws Exception {
+    void testParserForMissingStyleIdentifier() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         WMTSTileSource testSource = new WMTSTileSource(testMissingStyleIdentifier);
@@ -327,5 +328,5 @@
 
     @Test
-    public void testForMultipleTileMatricesForOneLayerProjection() throws Exception {
+    void testForMultipleTileMatricesForOneLayerProjection() throws Exception {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
         ImageryInfo copy = new ImageryInfo(testMultipleTileMatrixForLayer);
@@ -348,5 +349,5 @@
      */
     @Test
-    public void testDimension() throws IOException, WMTSGetCapabilitiesException {
+    void testDimension() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:21781"));
         ImageryInfo info = new ImageryInfo(testImageryGeoAdminCh);
@@ -363,5 +364,5 @@
 
     @Test
-    public void testDefaultLayer() throws Exception {
+    void testDefaultLayer() throws Exception {
         // https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/1.0.0/WMTSCapabilities.xml
         // do not use withFileBody as it needs different directory layout :(
@@ -412,6 +413,6 @@
     private void verifyTile(LatLon expected, WMTSTileSource source, int x, int y, int z) {
         LatLon ll = CoordinateConversion.coorToLL(source.tileXYToLatLon(x, y, z));
-        assertEquals("Latitude", expected.lat(), ll.lat(), 1e-05);
-        assertEquals("Longitude", expected.lon(), ll.lon(), 1e-05);
+        assertEquals(expected.lat(), ll.lat(), 1e-05, "Latitude");
+        assertEquals(expected.lon(), ll.lon(), 1e-05, "Longitude");
     }
 
@@ -424,10 +425,10 @@
         LatLon result = CoordinateConversion.coorToLL(testSource.tileXYToLatLon(x, y, z));
         LatLon expected = CoordinateConversion.coorToLL(verifier.tileXYToLatLon(x, y, z + zoomOffset));
-        assertEquals("Longitude", LatLon.normalizeLon(expected.lon() - result.lon()), 0.0, 1e-04);
-        assertEquals("Latitude", expected.lat(), result.lat(), 1e-04);
-    }
-
-    @Test
-    public void testGisKtnGvAt() throws IOException, WMTSGetCapabilitiesException {
+        assertEquals(0.0, LatLon.normalizeLon(expected.lon() - result.lon()), 1e-04, "Longitude");
+        assertEquals(expected.lat(), result.lat(), 1e-04, "Latitude");
+    }
+
+    @Test
+    void testGisKtnGvAt() throws IOException, WMTSGetCapabilitiesException {
         ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:31258"));
         final WMTSTileSource source = new WMTSTileSource(testImageryGisKtnGvAt);
Index: trunk/test/unit/org/openstreetmap/josm/data/osm/DefaultNameFormatterTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/osm/DefaultNameFormatterTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/data/osm/DefaultNameFormatterTest.java	(revision 18106)
@@ -5,6 +5,5 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.IOException;
@@ -16,6 +15,5 @@
 import java.util.stream.IntStream;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetReader;
@@ -23,8 +21,10 @@
 import org.openstreetmap.josm.io.IllegalDataException;
 import org.openstreetmap.josm.io.OsmReader;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 import org.xml.sax.SAXException;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -33,18 +33,14 @@
  * Unit tests of {@link DefaultNameFormatter} class.
  */
-public class DefaultNameFormatterTest {
-
-    /**
-     * Setup test.
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules();
-
+// Preferences are needed for OSM primitives
+@BasicPreferences
+@BasicWiremock
+@HTTP
+class DefaultNameFormatterTest {
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
@@ -56,12 +52,12 @@
     @Test
     @SuppressFBWarnings(value = "ITA_INEFFICIENT_TO_ARRAY")
-    public void testTicket9632() throws IllegalDataException, IOException, SAXException {
+    void testTicket9632() throws IllegalDataException, IOException, SAXException {
         String source = "presets/Presets_BicycleJunction-preset.xml";
-        wireMockRule.stubFor(get(urlEqualTo("/" + source))
+        wireMockServer.stubFor(get(urlEqualTo("/" + source))
                 .willReturn(aResponse()
                     .withStatus(200)
                     .withHeader("Content-Type", "text/xml")
                     .withBodyFile(source)));
-        TaggingPresets.addTaggingPresets(TaggingPresetReader.readAll(wireMockRule.url(source), true));
+        TaggingPresets.addTaggingPresets(TaggingPresetReader.readAll(wireMockServer.url(source), true));
 
         Comparator<IRelation<?>> comparator = DefaultNameFormatter.getInstance().getRelationComparator();
@@ -102,5 +98,5 @@
      */
     @Test
-    public void testRelationName() {
+    void testRelationName() {
         assertEquals("relation (0, 0 members)",
                 getFormattedRelationName("X=Y"));
@@ -123,5 +119,5 @@
      */
     @Test
-    public void testWayName() {
+    void testWayName() {
         assertEquals("\u200Ebuilding\u200E (0 nodes)\u200C", getFormattedWayName("building=yes"));
         assertEquals("\u200EHouse number 123\u200E (0 nodes)\u200C",
@@ -145,5 +141,5 @@
      */
     @Test
-    public void testFormatAsHtmlUnorderedList() {
+    void testFormatAsHtmlUnorderedList() {
         assertEquals("<ul><li>incomplete</li></ul>",
                 DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(new Node(1)));
@@ -159,5 +155,5 @@
      */
     @Test
-    public void testBuildDefaultToolTip() {
+    void testBuildDefaultToolTip() {
         assertEquals("<html><strong>id</strong>=0<br>"+
                            "<strong>name:en</strong>=foo<br>"+
@@ -173,5 +169,5 @@
      */
     @Test
-    public void testRemoveBiDiCharacters() {
+    void testRemoveBiDiCharacters() {
         assertEquals("building (0 nodes)", DefaultNameFormatter.removeBiDiCharacters("\u200Ebuilding\u200E (0 nodes)\u200C"));
     }
Index: trunk/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java	(revision 18106)
@@ -5,8 +5,7 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.net.CookieHandler;
@@ -15,32 +14,29 @@
 import java.util.Collections;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
 import org.openstreetmap.josm.data.oauth.OAuthParameters;
 import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.io.OsmTransferCanceledException;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 /**
  * Unit tests of {@link OsmOAuthAuthorizationClient} class.
  */
-public class OsmOAuthAuthorizationClientTest {
-
-    /**
-     * Setup tests
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().timeout(20000);
-
+@Timeout(20)
+@BasicWiremock
+// Needed for OAuthParameters
+@BasicPreferences
+@HTTP
+class OsmOAuthAuthorizationClientTest {
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort());
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
@@ -50,20 +46,21 @@
      */
     @Test
-    public void testOsmOAuthAuthorizationClient() throws OsmTransferCanceledException, OsmOAuthAuthorizationException {
+    void testOsmOAuthAuthorizationClient() throws OsmTransferCanceledException, OsmOAuthAuthorizationException {
         // request token
-        wireMockRule.stubFor(get(urlEqualTo("/oauth/request_token"))
+        wireMockServer.stubFor(get(urlEqualTo("/oauth/request_token"))
                 .willReturn(aResponse().withStatus(200).withBody(String.join("&",
                         "oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR",
                         "oauth_token_secret=nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB"))));
-        OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(OAuthParameters.createDefault(wireMockRule.url("/api")));
+        OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(OAuthParameters.createDefault(
+                wireMockServer.url("/api")));
 
         OAuthToken requestToken = client.getRequestToken(null);
-        assertEquals("requestToken.key", "entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR", requestToken.getKey());
-        assertEquals("requestToken.secret", "nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB", requestToken.getSecret());
+        assertEquals("entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR", requestToken.getKey(), "requestToken.key");
+        assertEquals("nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB", requestToken.getSecret(), "requestToken.secret");
         String url = client.getAuthoriseUrl(requestToken);
-        assertEquals("url", wireMockRule.url("/oauth/authorize?oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR"), url);
+        assertEquals(wireMockServer.url("/oauth/authorize?oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR"), url, "url");
 
         // access token
-        wireMockRule.stubFor(get(urlEqualTo("/oauth/access_token"))
+        wireMockServer.stubFor(get(urlEqualTo("/oauth/access_token"))
                 .willReturn(aResponse().withStatus(200).withBody(String.join("&",
                         "oauth_token=eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX",
@@ -71,6 +68,6 @@
 
         OAuthToken accessToken = client.getAccessToken(null);
-        assertEquals("accessToken.key", "eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX", accessToken.getKey());
-        assertEquals("accessToken.secret", "nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB", accessToken.getSecret());
+        assertEquals("eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX", accessToken.getKey(), "accessToken.key");
+        assertEquals("nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB", accessToken.getSecret(), "accessToken.secret");
     }
 
@@ -82,6 +79,6 @@
      */
     @Test
-    public void testCookieHandlingMock() throws Exception {
-        wireMockRule.stubFor(get(urlEqualTo("/login?cookie_test=true"))
+    void testCookieHandlingMock() throws Exception {
+        wireMockServer.stubFor(get(urlEqualTo("/login?cookie_test=true"))
                 .willReturn(aResponse()
                         .withStatus(200)
@@ -90,11 +87,11 @@
                         "name=\"authenticity_token\" " +
                         "value=\"fzp6CWJhp6Vns09re3s2Tw==\" />")));
-        final OAuthParameters parameters = OAuthParameters.createDefault(wireMockRule.url("/api"));
+        final OAuthParameters parameters = OAuthParameters.createDefault(wireMockServer.url("/api"));
         final OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(parameters);
         final OsmOAuthAuthorizationClient.SessionId sessionId = client.fetchOsmWebsiteSessionId();
         assertNotNull(sessionId);
-        assertEquals("sessionId.id", "7fe8e2ea36c6b803cb902301b28e0a", sessionId.id);
-        assertEquals("sessionId.token", "fzp6CWJhp6Vns09re3s2Tw==", sessionId.token);
-        assertNull("sessionId.userName", sessionId.userName);
+        assertEquals("7fe8e2ea36c6b803cb902301b28e0a", sessionId.id, "sessionId.id");
+        assertEquals("fzp6CWJhp6Vns09re3s2Tw==", sessionId.token, "sessionId.token");
+        assertNull(sessionId.userName, "sessionId.userName");
     }
 
@@ -106,5 +103,5 @@
      */
     @Test
-    public void testCookieHandlingCookieManager() throws Exception {
+    void testCookieHandlingCookieManager() throws Exception {
         // emulate Java Web Start behaviour
         // see https://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/accessingCookies.html
Index: trunk/test/unit/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTaskTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTaskTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTaskTest.java	(revision 18106)
@@ -5,41 +5,35 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import javax.swing.JLabel;
 import java.awt.Component;
 
-import javax.swing.JLabel;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.openstreetmap.josm.TestUtils;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 import org.openstreetmap.josm.tools.Logging;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 /**
  * Unit tests of {@link ApiUrlTestTask} class.
  */
-public class ApiUrlTestTaskTest {
-
-    /**
-     * Setup tests
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences().timeout(30000);
-
+@Timeout(30)
+@BasicPreferences
+@BasicWiremock
+@HTTP
+class ApiUrlTestTaskTest {
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     private static final Component PARENT = new JLabel();
@@ -48,7 +42,7 @@
      * Unit test of {@link ApiUrlTestTask#ApiUrlTestTask} - null url.
      */
-    @Test(expected = IllegalArgumentException.class)
-    public void testNullApiUrl() {
-        new ApiUrlTestTask(PARENT, null);
+    @Test
+    void testNullApiUrl() {
+        assertThrows(IllegalArgumentException.class, () -> new ApiUrlTestTask(PARENT, null));
     }
 
@@ -57,6 +51,6 @@
      */
     @Test
-    public void testNominalUrl() {
-        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockRule.url("/__files/api"));
+    void testNominalUrl() {
+        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockServer.url("/__files/api"));
         task.run();
         assertTrue(task.isSuccess());
@@ -67,5 +61,5 @@
      */
     @Test
-    public void testAlertInvalidUrl() {
+    void testAlertInvalidUrl() {
         Logging.clearLastErrorAndWarnings();
         ApiUrlTestTask task = new ApiUrlTestTask(PARENT, "malformed url");
@@ -80,5 +74,5 @@
      */
     @Test
-    public void testUnknownHost() {
+    void testUnknownHost() {
         Logging.clearLastErrorAndWarnings();
         ApiUrlTestTask task = new ApiUrlTestTask(PARENT, "http://unknown");
@@ -93,10 +87,10 @@
      */
     @Test
-    public void testAlertInvalidServerResult() {
+    void testAlertInvalidServerResult() {
         Logging.clearLastErrorAndWarnings();
-        wireMockRule.stubFor(get(urlEqualTo("/does-not-exist/0.6/capabilities"))
+        wireMockServer.stubFor(get(urlEqualTo("/does-not-exist/0.6/capabilities"))
                 .willReturn(aResponse().withStatus(404)));
 
-        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockRule.url("/does-not-exist"));
+        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockServer.url("/does-not-exist"));
         task.run();
         assertFalse(task.isSuccess());
@@ -109,12 +103,12 @@
      */
     @Test
-    public void testAlertInvalidCapabilities() {
+    void testAlertInvalidCapabilities() {
         Logging.clearLastErrorAndWarnings();
-        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockRule.url("/__files/invalid_api"));
+        ApiUrlTestTask task = new ApiUrlTestTask(PARENT, wireMockServer.url("/__files/invalid_api"));
         task.run();
         assertFalse(task.isSuccess());
         assertThat(Logging.getLastErrorAndWarnings().toString(), containsString(
                 "The OSM API server at 'XXX' did not return a valid response.<br>It is likely that 'XXX' is not an OSM API server."
-                        .replace("XXX", wireMockRule.url("/__files/invalid_api"))));
+                        .replace("XXX", wireMockServer.url("/__files/invalid_api"))));
     }
 }
Index: trunk/test/unit/org/openstreetmap/josm/io/OsmServerHistoryReaderTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmServerHistoryReaderTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/io/OsmServerHistoryReaderTest.java	(revision 18106)
@@ -2,12 +2,10 @@
 package org.openstreetmap.josm.io;
 
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
-import org.openstreetmap.josm.TestUtils;
+import java.time.Instant;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.history.History;
@@ -15,27 +13,29 @@
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-
-import java.time.Instant;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 /**
  * Unit tests of {@link OsmServerHistoryReader} class.
  */
-public class OsmServerHistoryReaderTest {
-
+@BasicPreferences
+@BasicWiremock
+@HTTP
+class OsmServerHistoryReaderTest {
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
      * Setup tests.
      */
-    @Before
-    public void setUp() {
-        JOSMFixture.createUnitTestFixture().init();
-        Config.getPref().put("osm-server.url", wireMockRule.url("/__files/api"));
+    @BeforeEach
+    void setUp() {
+        Config.getPref().put("osm-server.url", wireMockServer.url("/__files/api"));
     }
 
@@ -45,5 +45,5 @@
      */
     @Test
-    public void testNode() throws OsmTransferException {
+    void testNode() throws OsmTransferException {
         OsmServerHistoryReader reader = new OsmServerHistoryReader(OsmPrimitiveType.NODE, 266187);
         HistoryDataSet ds = reader.parseHistory(NullProgressMonitor.INSTANCE);
@@ -60,5 +60,5 @@
      */
     @Test
-    public void testWay() throws OsmTransferException {
+    void testWay() throws OsmTransferException {
         OsmServerHistoryReader reader = new OsmServerHistoryReader(OsmPrimitiveType.WAY, 3058844);
         HistoryDataSet ds = reader.parseHistory(NullProgressMonitor.INSTANCE);
@@ -80,5 +80,5 @@
      */
     @Test
-    public void testRelation() throws OsmTransferException {
+    void testRelation() throws OsmTransferException {
         OsmServerHistoryReader reader = new OsmServerHistoryReader(OsmPrimitiveType.RELATION, 49);
         HistoryDataSet ds = reader.parseHistory(NullProgressMonitor.INSTANCE);
Index: trunk/test/unit/org/openstreetmap/josm/io/OverpassDownloadReaderTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OverpassDownloadReaderTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/io/OverpassDownloadReaderTest.java	(revision 18106)
@@ -5,9 +5,8 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.StringReader;
@@ -15,36 +14,29 @@
 import java.util.regex.Matcher;
 
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.openstreetmap.josm.TestUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.io.OverpassDownloadReader.OverpassOutputFormat;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 import org.openstreetmap.josm.tools.SearchCompilerQueryWizard;
 import org.openstreetmap.josm.tools.Utils;
 import org.openstreetmap.josm.tools.date.DateUtils;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 /**
  * Unit tests of {@link OverpassDownloadReader} class.
  */
-public class OverpassDownloadReaderTest {
-
-    /**
-     * Base test environment is enough
-     */
-    @Rule
-    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().preferences();
-
+@BasicWiremock
+@BasicPreferences
+@HTTP
+class OverpassDownloadReaderTest {
     /**
      * HTTP mock.
      */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()));
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     private static final String NOMINATIM_URL_PATH = "/search?format=xml&q=";
@@ -53,7 +45,7 @@
      * Setup test.
      */
-    @Before
+    @BeforeEach
     public void setUp() {
-        NameFinder.NOMINATIM_URL_PROP.put(wireMockRule.url(NOMINATIM_URL_PATH));
+        NameFinder.NOMINATIM_URL_PROP.put(wireMockServer.url(NOMINATIM_URL_PATH));
     }
 
@@ -70,5 +62,5 @@
      */
     @Test
-    public void testBbox() {
+    void testBbox() {
         final String query = getExpandedQuery("amenity=drinking_water");
         assertEquals("" +
@@ -82,5 +74,5 @@
 
     private void stubNominatim(String query) {
-        wireMockRule.stubFor(get(urlEqualTo(NOMINATIM_URL_PATH + query))
+        wireMockServer.stubFor(get(urlEqualTo(NOMINATIM_URL_PATH + query))
                 .willReturn(aResponse()
                     .withStatus(200)
@@ -93,5 +85,5 @@
      */
     @Test
-    public void testDate() {
+    void testDate() {
         LocalDateTime from = LocalDateTime.of(2017, 7, 14, 2, 40);
         assertEquals("2016-07-14T02:40:00Z", OverpassDownloadReader.date("1 year", from));
@@ -119,5 +111,5 @@
      */
     @Test
-    public void testDateNewer() {
+    void testDateNewer() {
         String query = getExpandedQuery("type:node and newer:3minutes");
         String statement = query.substring(query.indexOf("node(newer:\"") + 12, query.lastIndexOf("\");"));
@@ -133,5 +125,5 @@
      */
     @Test
-    public void testGeocodeArea() {
+    void testGeocodeArea() {
         stubNominatim("London");
         final String query = getExpandedQuery("amenity=drinking_water in London");
@@ -150,5 +142,5 @@
      */
     @Test
-    public void testGeocodeUnknownArea() {
+    void testGeocodeUnknownArea() {
         stubNominatim("foo-bar-baz-does-not-exist");
         final String query = OverpassDownloadReader.expandExtendedQueries("{{geocodeArea:foo-bar-baz-does-not-exist}}");
@@ -160,5 +152,5 @@
      */
     @Test
-    public void testOutputFormatStatement() {
+    void testOutputFormatStatement() {
         for (OverpassOutputFormat oof : OverpassOutputFormat.values()) {
             Matcher m = OverpassDownloadReader.OUTPUT_FORMAT_STATEMENT.matcher("[out:"+oof.getDirective()+"]");
@@ -182,5 +174,5 @@
      */
     @Test
-    public void testFixQuery() {
+    void testFixQuery() {
         assertNull(OverpassDownloadReader.fixQuery(null));
 
@@ -224,5 +216,5 @@
      */
     @Test
-    public void testSearchName() throws Exception {
+    void testSearchName() throws Exception {
         try (StringReader reader = new StringReader(NameFinderTest.SAMPLE)) {
             assertEquals(1942586L,
Index: trunk/test/unit/org/openstreetmap/josm/io/imagery/WMSImageryTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/imagery/WMSImageryTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/io/imagery/WMSImageryTest.java	(revision 18106)
@@ -2,7 +2,7 @@
 package org.openstreetmap.josm.io.imagery;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
@@ -11,13 +11,13 @@
 import java.util.List;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
 
+import com.github.tomakehurst.wiremock.WireMockServer;
 import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -26,21 +26,22 @@
  * Unit tests of {@link WMSImagery} class.
  */
-public class WMSImageryTest {
+@BasicWiremock
+class WMSImageryTest {
 
     /**
      * Setup test
      */
-    @Rule
+    @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules().projection();
+    JOSMTestRules test = new JOSMTestRules().projection();
 
-    @Rule
-    public WireMockRule tileServer = new WireMockRule(WireMockConfiguration.options()
-            .dynamicPort());
+    @BasicWiremock
+    WireMockServer tileServer;
+
     /**
      * Unit test of {@code WMSImagery.WMSGetCapabilitiesException} class
      */
     @Test
-    public void testWMSGetCapabilitiesException() {
+    void testWMSGetCapabilitiesException() {
         Exception cause = new Exception("test");
         WMSGetCapabilitiesException exc = new WMSGetCapabilitiesException(cause, "bar");
@@ -58,5 +59,5 @@
      */
     @Test
-    public void testTicket15730() throws IOException, WMSGetCapabilitiesException {
+    void testTicket15730() throws IOException, WMSGetCapabilitiesException {
         tileServer.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(WireMock.aResponse().withBody(
                 Files.readAllBytes(Paths.get(TestUtils.getRegressionDataDir(15730), "capabilities.xml"))
@@ -69,5 +70,5 @@
 
     @Test
-    public void testNestedLayers() throws Exception {
+    void testNestedLayers() throws Exception {
         tileServer.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(WireMock.aResponse().withBody(
                 Files.readAllBytes(Paths.get(TestUtils.getTestDataRoot() + "wms/mapa-um-warszawa-pl.xml")))));
@@ -84,5 +85,5 @@
      */
     @Test
-    public void testTicket16248() throws IOException, WMSGetCapabilitiesException {
+    void testTicket16248() throws IOException, WMSGetCapabilitiesException {
         byte[] capabilities = Files.readAllBytes(Paths.get(TestUtils.getRegressionDataFile(16248, "capabilities.xml")));
         tileServer.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(WireMock.aResponse().withBody(capabilities)));
@@ -101,5 +102,5 @@
      */
     @Test
-    public void testTicket19193() throws IOException, WMSGetCapabilitiesException {
+    void testTicket19193() throws IOException, WMSGetCapabilitiesException {
         byte[] capabilities = Files.readAllBytes(Paths.get(TestUtils.getRegressionDataFile(19193, "capabilities.xml")));
         tileServer.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(WireMock.aResponse().withBody(capabilities)));
@@ -120,5 +121,5 @@
      */
     @Test
-    public void testTicket16333() throws IOException, WMSGetCapabilitiesException {
+    void testTicket16333() throws IOException, WMSGetCapabilitiesException {
         tileServer.stubFor(
                 WireMock.get(WireMock.anyUrl())
@@ -129,5 +130,5 @@
         WMSImagery wms = new WMSImagery(tileServer.url("any"));
         assertEquals("https://duinoord.xs4all.nl/geoserver/ows?SERVICE=WMS&", wms.buildRootUrl());
-        assertEquals(null, wms.getLayers().get(0).getName());
+        assertNull(wms.getLayers().get(0).getName());
         assertEquals("", wms.getLayers().get(0).getTitle());
 
@@ -137,5 +138,5 @@
 
     @Test
-    public void testForTitleWithinAttribution_ticket16940() throws IOException, WMSGetCapabilitiesException {
+    void testForTitleWithinAttribution_ticket16940() throws IOException, WMSGetCapabilitiesException {
         tileServer.stubFor(
                 WireMock.get(WireMock.anyUrl())
@@ -148,3 +149,2 @@
     }
 }
-
Index: trunk/test/unit/org/openstreetmap/josm/testutils/annotations/AnnotationUtils.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/testutils/annotations/AnnotationUtils.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/testutils/annotations/AnnotationUtils.java	(revision 18106)
@@ -17,5 +17,5 @@
  * @since 18037
  */
-final class AnnotationUtils {
+public final class AnnotationUtils {
     private AnnotationUtils() {
         // Utils class
Index: trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicWiremock.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicWiremock.java	(revision 18106)
+++ trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicWiremock.java	(revision 18106)
@@ -0,0 +1,218 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.testutils.annotations;
+
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.junit.platform.commons.support.AnnotationSupport;
+import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Pair;
+import org.openstreetmap.josm.tools.Utils;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
+import com.github.tomakehurst.wiremock.verification.LoggedRequest;
+
+/**
+ * Create a basic wiremock environment. If you need the actual WireMockServer, annotate a field or parameter
+ * with {@code @BasicWiremock}.
+ *
+ * @author Taylor Smock
+ * @see OsmApiExtension (this sets the Osm Api to the wiremock URL)
+ * @since 18106
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
+@ExtendWith(BasicWiremock.WireMockExtension.class)
+public @interface BasicWiremock {
+    /**
+     * Set the path for the data. Default is {@link TestUtils#getTestDataRoot()}.
+     * @return The path ({@code ""} for the default)
+     */
+    String value() default "";
+
+    /**
+     * {@link ResponseTransformer} for use with the WireMock server.
+     * Current constructors supported:
+     * <ul>
+     *     <li>{@code new ResponseTransformer()}</li>
+     *     <li>{@code new ResponseTransformer(ExtensionContext context)}</li>
+     * </ul>
+     * @return The transformers to instantiate
+     */
+    Class<? extends ResponseTransformer>[] responseTransformers() default {};
+
+    /**
+     * Start/stop WireMock automatically, and check for missed calls.
+     * @author Taylor Smock
+     *
+     */
+    class WireMockExtension
+            implements AfterAllCallback, AfterEachCallback, BeforeAllCallback, BeforeEachCallback, ParameterResolver {
+        /**
+         * Get the default wiremock server
+         * @param context The context to search
+         * @return The wiremock server
+         */
+        static WireMockServer getWiremock(ExtensionContext context) {
+            ExtensionContext.Namespace namespace = ExtensionContext.Namespace.create(BasicWiremock.class);
+            BasicWiremock annotation = AnnotationUtils.findFirstParentAnnotation(context, BasicWiremock.class)
+                    .orElseThrow(() -> new IllegalArgumentException("There must be a @BasicWiremock annotation"));
+            return context.getStore(namespace).getOrComputeIfAbsent(WireMockServer.class, clazz -> {
+                final List<ResponseTransformer> transformers = new ArrayList<>(annotation.responseTransformers().length);
+                for (Class<? extends ResponseTransformer> responseTransformer : annotation.responseTransformers()) {
+                    for (Pair<Class<?>[], Object[]> parameterMapping : Arrays.asList(
+                            new Pair<>(new Class<?>[] {ExtensionContext.class }, new Object[] {context }),
+                            new Pair<>(new Class<?>[0], new Object[0]))) {
+                        try {
+                            Constructor<? extends ResponseTransformer> constructor = responseTransformer
+                                    .getConstructor(parameterMapping.a);
+                            transformers.add(constructor.newInstance(parameterMapping.b));
+                            break;
+                        } catch (ReflectiveOperationException e) {
+                            fail(e);
+                        }
+                    }
+                }
+                return new WireMockServer(
+                    options().usingFilesUnderDirectory(Utils.isStripEmpty(annotation.value()) ? TestUtils.getTestDataRoot() :
+                            annotation.value()).extensions(transformers.toArray(new ResponseTransformer[0])).dynamicPort());
+            }, WireMockServer.class);
+        }
+
+        /**
+         * Replace URL servers with wiremock
+         *
+         * @param wireMockServer The wiremock to point to
+         * @param url            The URL to fix
+         * @return A url that points at the wiremock server
+         */
+        public static String replaceUrl(WireMockServer wireMockServer, String url) {
+            try {
+                URL temp = new URL(url);
+                return wireMockServer.baseUrl() + temp.getFile();
+            } catch (MalformedURLException error) {
+                Logging.error(error);
+            }
+            return null;
+        }
+
+        @Override
+        public void afterAll(ExtensionContext context) throws Exception {
+            // Run in EDT to avoid stopping wiremock server before wiremock requests finish.
+            GuiHelper.runInEDTAndWait(getWiremock(context)::stop);
+        }
+
+        @Override
+        public void afterEach(ExtensionContext context) throws Exception {
+            List<LoggedRequest> missed = getWiremock(context).findUnmatchedRequests().getRequests();
+            missed.forEach(r -> Logging.error(r.getAbsoluteUrl()));
+            try {
+                assertTrue(missed.isEmpty(), missed.stream().map(LoggedRequest::getUrl).collect(Collectors.joining("\n\n")));
+            } finally {
+                getWiremock(context).resetRequests();
+                getWiremock(context).resetToDefaultMappings();
+                getWiremock(context).resetScenarios();
+                if (AnnotationUtils.elementIsAnnotated(context.getElement(), BasicWiremock.class)
+                        || getWiremock(context) == null) {
+                    this.afterAll(context);
+                }
+            }
+        }
+
+        @Override
+        public void beforeAll(ExtensionContext context) throws Exception {
+            getWiremock(context).start();
+        }
+
+        @Override
+        public void beforeEach(ExtensionContext context) throws Exception {
+            if (AnnotationUtils.elementIsAnnotated(context.getElement(), BasicWiremock.class) || getWiremock(context) == null) {
+                this.beforeAll(context);
+            }
+            if (context.getTestClass().isPresent()) {
+                List<Field> wireMockFields = AnnotationSupport.findAnnotatedFields(context.getRequiredTestClass(), BasicWiremock.class);
+                for (Field field : wireMockFields) {
+                    if (WireMockServer.class.isAssignableFrom(field.getType())) {
+                        final boolean isAccessible = field.isAccessible();
+                        field.setAccessible(true);
+                        try {
+                            field.set(context.getTestInstance().orElse(null), getWiremock(context));
+                        } finally {
+                            field.setAccessible(isAccessible);
+                        }
+                    } else {
+                        throw new IllegalArgumentException("@BasicWiremock: cannot set field of type " + field.getType().getName());
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
+                throws ParameterResolutionException {
+            return parameterContext.getParameter().getAnnotation(BasicWiremock.class) != null
+                    && parameterContext.getParameter().getType() == WireMockServer.class;
+        }
+
+        @Override
+        public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
+                throws ParameterResolutionException {
+            return getWiremock(extensionContext);
+        }
+    }
+
+    /**
+     * A class specifically to mock OSM API calls
+     */
+    class OsmApiExtension extends WireMockExtension {
+        @Override
+        public void afterAll(ExtensionContext context) throws Exception {
+            try {
+                super.afterAll(context);
+            } finally {
+                Config.getPref().put("osm-server.url", "https://invalid.url");
+            }
+        }
+
+        @Override
+        public void beforeAll(ExtensionContext context) throws Exception {
+            if (!AnnotationSupport.isAnnotated(context.getElement(), BasicPreferences.class)) {
+                fail("OsmApiExtension requires @BasicPreferences");
+            }
+            super.beforeAll(context);
+            Config.getPref().put("osm-server.url", getWiremock(context).baseUrl());
+            OsmApi.getOsmApi().initialize(NullProgressMonitor.INSTANCE);
+        }
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/testutils/annotations/HTTP.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/testutils/annotations/HTTP.java	(revision 18106)
+++ trunk/test/unit/org/openstreetmap/josm/testutils/annotations/HTTP.java	(revision 18106)
@@ -0,0 +1,63 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.testutils.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.net.URL;
+import java.util.Optional;
+
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.support.AnnotationSupport;
+import org.junit.platform.commons.support.ReflectionSupport;
+import org.openstreetmap.josm.tools.Http1Client;
+import org.openstreetmap.josm.tools.HttpClient;
+
+/**
+ * Set up the HttpClient factory
+ * @author Taylor Smock
+ * @since 18106
+ */
+@Documented
+@Retention(RUNTIME)
+@Target(TYPE)
+@ExtendWith(HTTP.HTTPExtension.class)
+public @interface HTTP {
+    /**
+     * Set the HttpClient type
+     * Note that {@link HttpClient#HttpClient(URL, String)} must be accessible.
+     *
+     * @return The client type to create
+     */
+    Class<? extends HttpClient> value() default Http1Client.class;
+
+    /**
+     * Initialize and reset HttpClient
+     * @author Taylor Smock
+     *
+     */
+    class HTTPExtension implements BeforeAllCallback, AfterAllCallback {
+        @Override
+        public void afterAll(ExtensionContext context) throws Exception {
+            AnnotationUtils.resetStaticClass(HttpClient.class);
+        }
+
+        @Override
+        public void beforeAll(ExtensionContext context) throws Exception {
+            final Class<? extends HttpClient> clientFactory;
+            final Optional<HTTP> annotation = AnnotationSupport.findAnnotation(context.getElement(), HTTP.class);
+            if (annotation.isPresent()) {
+                clientFactory = annotation.get().value();
+            } else {
+                clientFactory = Http1Client.class;
+            }
+            HttpClient.setFactory((url, method) -> ReflectionSupport.newInstance(clientFactory, url, method));
+        }
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/tools/bugreport/BugReportSenderTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/tools/bugreport/BugReportSenderTest.java	(revision 18100)
+++ trunk/test/unit/org/openstreetmap/josm/tools/bugreport/BugReportSenderTest.java	(revision 18106)
@@ -8,42 +8,34 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.verify;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.net.URI;
 import java.util.List;
 
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.actions.ShowStatusReportAction;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
+import org.openstreetmap.josm.testutils.annotations.HTTP;
 import org.openstreetmap.josm.testutils.mockers.OpenBrowserMocker;
 
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.WireMockServer;
 
 /**
  * Unit tests of {@link BugReportSender} class.
  */
-public class BugReportSenderTest {
-
+@BasicPreferences
+@BasicWiremock
+@HTTP
+class BugReportSenderTest {
     /**
-     * Setup tests.
+     * HTTP mock
      */
-    @Before
-    public void setUp() {
-        JOSMFixture.createUnitTestFixture().init();
-    }
-
-    /**
-     * HTTP mock.
-     */
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort());
+    @BasicWiremock
+    WireMockServer wireMockServer;
 
     /**
@@ -52,7 +44,7 @@
      */
     @Test
-    public void testBugReportSender() throws InterruptedException {
-        Config.getPref().put("josm.url", wireMockRule.baseUrl());
-        wireMockRule.stubFor(post(urlEqualTo("/josmticket"))
+    void testBugReportSender() throws InterruptedException {
+        Config.getPref().put("josm.url", wireMockServer.baseUrl());
+        wireMockServer.stubFor(post(urlEqualTo("/josmticket"))
                 .willReturn(aResponse()
                         .withStatus(200)
@@ -74,9 +66,9 @@
         assertFalse(sender.isAlive());
         assertNull(sender.getErrorMessage(), sender.getErrorMessage());
-        verify(exactly(1), postRequestedFor(urlEqualTo("/josmticket")).withRequestBody(containing("pdata=")));
+        wireMockServer.verify(exactly(1), postRequestedFor(urlEqualTo("/josmticket")).withRequestBody(containing("pdata=")));
 
         List<URI> calledURIs = OpenBrowserMocker.getCalledURIs();
         assertEquals(1, calledURIs.size());
-        assertEquals(wireMockRule.url("/josmticket?pdata_stored=6bccff5c0417217bfbbe5fff"), calledURIs.get(0).toString());
+        assertEquals(wireMockServer.url("/josmticket?pdata_stored=6bccff5c0417217bfbbe5fff"), calledURIs.get(0).toString());
     }
 }
