Merge "SubmoduleSubscriptionsWholeTopicMergeIT: cleanup last method."
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index b435bcc..68b0699 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -130,7 +130,6 @@
 import com.google.gerrit.testing.FakeGroupAuditService;
 import com.google.gerrit.testing.NoteDbMode;
 import com.google.gerrit.testing.SshMode;
-import com.google.gerrit.testing.TempFileUtil;
 import com.google.gson.Gson;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.SchemaFactory;
@@ -182,8 +181,10 @@
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runner.RunWith;
@@ -194,6 +195,8 @@
   private static GerritServer commonServer;
   private static Description firstTest;
 
+  @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   @ConfigSuite.Parameter public Config baseConfig;
   @ConfigSuite.Name private String configName;
 
@@ -336,7 +339,6 @@
         commonServer = null;
       }
     }
-    TempFileUtil.cleanup();
   }
 
   /** Controls which project and branches should be reset after each test case. */
@@ -415,11 +417,11 @@
     Module module = createModule();
     if (classDesc.equals(methodDesc) && !classDesc.sandboxed() && !methodDesc.sandboxed()) {
       if (commonServer == null) {
-        commonServer = GerritServer.initAndStart(classDesc, baseConfig, module);
+        commonServer = GerritServer.initAndStart(temporaryFolder, classDesc, baseConfig, module);
       }
       server = commonServer;
     } else {
-      server = GerritServer.initAndStart(methodDesc, baseConfig, module);
+      server = GerritServer.initAndStart(temporaryFolder, methodDesc, baseConfig, module);
     }
 
     server.getTestInjector().injectMembers(this);
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 063b298..981ee6b 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -51,7 +51,6 @@
 import com.google.gerrit.testing.NoteDbChecker;
 import com.google.gerrit.testing.NoteDbMode;
 import com.google.gerrit.testing.SshMode;
-import com.google.gerrit.testing.TempFileUtil;
 import com.google.inject.AbstractModule;
 import com.google.inject.Injector;
 import com.google.inject.Key;
@@ -81,6 +80,7 @@
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.RepositoryCache;
 import org.eclipse.jgit.util.FS;
+import org.junit.rules.TemporaryFolder;
 
 public class GerritServer implements AutoCloseable {
   public static class StartupException extends Exception {
@@ -290,11 +290,11 @@
   /**
    * Initializes new Gerrit site and returns started server.
    *
-   * <p>A new temporary directory for the site will be created with {@link TempFileUtil}, even in
+   * <p>A new temporary directory for the site will be created with {@code temporaryFolder}, even in
    * the server is otherwise configured in-memory. Closing the server stops the daemon but does not
-   * delete the temporary directory. Callers may either get the directory with {@link
-   * #getSitePath()} and delete it manually, or call {@link TempFileUtil#cleanup()}.
+   * delete the temporary directory..
    *
+   * @param temporaryFolder helper rule for creating site directories.
    * @param desc server description.
    * @param baseConfig default config values; merged with config from {@code desc}.
    * @param testSysModule additional Guice module to use.
@@ -302,15 +302,18 @@
    * @throws Exception
    */
   public static GerritServer initAndStart(
-      Description desc, Config baseConfig, @Nullable Module testSysModule) throws Exception {
-    Path site = TempFileUtil.createTempDirectory().toPath();
+      TemporaryFolder temporaryFolder,
+      Description desc,
+      Config baseConfig,
+      @Nullable Module testSysModule)
+      throws Exception {
+    Path site = temporaryFolder.newFolder().toPath();
     try {
       if (!desc.memory()) {
         init(desc, baseConfig, site);
       }
       return start(desc, baseConfig, site, testSysModule, null, null);
     } catch (Exception e) {
-      TempFileUtil.recursivelyDelete(site.toFile());
       throw e;
     }
   }
diff --git a/java/com/google/gerrit/testing/TempFileUtil.java b/java/com/google/gerrit/testing/TempFileUtil.java
deleted file mode 100644
index c42bd74..0000000
--- a/java/com/google/gerrit/testing/TempFileUtil.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.testing;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class TempFileUtil {
-  private static List<File> allDirsCreated = new ArrayList<>();
-
-  public static synchronized File createTempDirectory() throws IOException {
-    File tmp = File.createTempFile("gerrit_test_", "").getCanonicalFile();
-    if (!tmp.delete() || !tmp.mkdir()) {
-      throw new IOException("Cannot create " + tmp.getPath());
-    }
-    allDirsCreated.add(tmp);
-    return tmp;
-  }
-
-  public static synchronized void cleanup() throws IOException {
-    for (File dir : allDirsCreated) {
-      recursivelyDelete(dir);
-    }
-    allDirsCreated.clear();
-  }
-
-  public static void recursivelyDelete(File dir) throws IOException {
-    if (!dir.getPath().equals(dir.getCanonicalPath())) {
-      // Directory symlink reaching outside of temporary space.
-      return;
-    }
-    File[] contents = dir.listFiles();
-    if (contents != null) {
-      for (File d : contents) {
-        if (d.isDirectory()) {
-          recursivelyDelete(d);
-        } else {
-          deleteNowOrOnExit(d);
-        }
-      }
-    }
-    deleteNowOrOnExit(dir);
-  }
-
-  private static void deleteNowOrOnExit(File dir) {
-    if (!dir.delete()) {
-      dir.deleteOnExit();
-    }
-  }
-
-  private TempFileUtil() {}
-}
diff --git a/javatests/com/google/gerrit/acceptance/BUILD b/javatests/com/google/gerrit/acceptance/BUILD
index 32804ef..54b3626 100644
--- a/javatests/com/google/gerrit/acceptance/BUILD
+++ b/javatests/com/google/gerrit/acceptance/BUILD
@@ -6,6 +6,7 @@
     deps = [
         "//java/com/google/gerrit/acceptance:lib",
         "//java/com/google/gerrit/server/util/time",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/jgit/org.eclipse.jgit:jgit",
         "//lib/truth",
diff --git a/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java b/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
index 49c23e3..69fdc7e 100644
--- a/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
+++ b/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
@@ -18,13 +18,14 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.File;
 import java.nio.file.Files;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.util.FS;
 import org.junit.Test;
 
-public class MergeableFileBasedConfigTest {
+public class MergeableFileBasedConfigTest extends GerritBaseTests {
   @Test
   public void mergeNull() throws Exception {
     MergeableFileBasedConfig cfg = newConfig();
diff --git a/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java b/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java
deleted file mode 100644
index 2bb3dca..0000000
--- a/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.acceptance.rest;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.truth.Truth.assertWithMessage;
-import static org.apache.http.HttpStatus.SC_FORBIDDEN;
-import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
-import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
-import static org.apache.http.HttpStatus.SC_NOT_FOUND;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
-import java.util.List;
-import java.util.Optional;
-import org.apache.commons.lang.StringUtils;
-import org.junit.Ignore;
-
-/**
- * Base class for testing the REST API bindings.
- *
- * <p>This test sends a request to each REST endpoint and verifies that an implementation is found
- * (no '404 Not Found' response) and that the request doesn't fail (no '500 Internal Server Error'
- * response). It doesn't verify that the REST endpoint works correctly. This is okay since the
- * purpose of the test is only to verify that the REST endpoint implementations are correctly bound.
- */
-@Ignore
-public abstract class AbstractRestApiBindingsTest extends AbstractDaemonTest {
-  protected void execute(List<RestCall> restCalls, String... args) throws Exception {
-    execute(restCalls, () -> {}, args);
-  }
-
-  protected void execute(List<RestCall> restCalls, BeforeRestCall beforeRestCall, String... args)
-      throws Exception {
-    for (RestCall restCall : restCalls) {
-      beforeRestCall.run();
-      execute(restCall, args);
-    }
-  }
-
-  protected void execute(RestCall restCall, String... args) throws Exception {
-    String method = restCall.httpMethod().name();
-    String uri = restCall.uri(args);
-
-    RestResponse response;
-    switch (restCall.httpMethod()) {
-      case GET:
-        response = adminRestSession.get(uri);
-        break;
-      case PUT:
-        response = adminRestSession.put(uri);
-        break;
-      case POST:
-        response = adminRestSession.post(uri);
-        break;
-      case DELETE:
-        response = adminRestSession.delete(uri);
-        break;
-      default:
-        fail("unsupported method: %s", restCall.httpMethod().name());
-        throw new IllegalStateException();
-    }
-
-    int status = response.getStatusCode();
-    String body = response.hasContent() ? response.getEntityContent() : "";
-
-    String msg = String.format("%s %s returned %d: %s", method, uri, status, body);
-    if (restCall.expectedResponseCode().isPresent()) {
-      assertWithMessage(msg).that(status).isEqualTo(restCall.expectedResponseCode().get());
-      if (restCall.expectedMessage().isPresent()) {
-        assertWithMessage(msg).that(body).contains(restCall.expectedMessage().get());
-      }
-    } else {
-      assertWithMessage(msg)
-          .that(status)
-          .isNotIn(ImmutableList.of(SC_FORBIDDEN, SC_NOT_FOUND, SC_METHOD_NOT_ALLOWED));
-      assertWithMessage(msg).that(status).isLessThan(SC_INTERNAL_SERVER_ERROR);
-    }
-  }
-
-  enum Method {
-    GET,
-    PUT,
-    POST,
-    DELETE
-  }
-
-  @AutoValue
-  abstract static class RestCall {
-    static RestCall get(String uriFormat) {
-      return builder(Method.GET, uriFormat).build();
-    }
-
-    static RestCall put(String uriFormat) {
-      return builder(Method.PUT, uriFormat).build();
-    }
-
-    static RestCall post(String uriFormat) {
-      return builder(Method.POST, uriFormat).build();
-    }
-
-    static RestCall delete(String uriFormat) {
-      return builder(Method.DELETE, uriFormat).build();
-    }
-
-    static Builder builder(Method httpMethod, String uriFormat) {
-      return new AutoValue_AbstractRestApiBindingsTest_RestCall.Builder()
-          .httpMethod(httpMethod)
-          .uriFormat(uriFormat);
-    }
-
-    abstract Method httpMethod();
-
-    abstract String uriFormat();
-
-    abstract Optional<Integer> expectedResponseCode();
-
-    abstract Optional<String> expectedMessage();
-
-    String uri(String... args) {
-      String uriFormat = uriFormat();
-      int expectedArgNum = StringUtils.countMatches(uriFormat, "%s");
-      checkState(
-          args.length == expectedArgNum,
-          "uriFormat %s needs %s arguments, got only %s: %s",
-          uriFormat,
-          expectedArgNum,
-          args.length,
-          args);
-      return String.format(uriFormat, (Object[]) args);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder {
-      abstract Builder httpMethod(Method httpMethod);
-
-      abstract Builder uriFormat(String uriFormat);
-
-      abstract Builder expectedResponseCode(int expectedResponseCode);
-
-      abstract Builder expectedMessage(String expectedMessage);
-
-      abstract RestCall build();
-    }
-  }
-
-  @FunctionalInterface
-  public interface BeforeRestCall {
-    void run() throws Exception;
-  }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/BUILD b/javatests/com/google/gerrit/acceptance/rest/BUILD
index b94a98d..84887da 100644
--- a/javatests/com/google/gerrit/acceptance/rest/BUILD
+++ b/javatests/com/google/gerrit/acceptance/rest/BUILD
@@ -2,23 +2,9 @@
 
 acceptance_tests(
     srcs = glob(["*IT.java"]),
-    group = "rest_bindings",
+    group = "rest_bindings_collection",
     labels = ["rest"],
     deps = [
-        ":util",
         "//java/com/google/gerrit/server/logging",
     ],
 )
-
-java_library(
-    name = "util",
-    testonly = 1,
-    srcs = [
-        "AbstractRestApiBindingsTest.java",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        "//java/com/google/gerrit/acceptance:lib",
-        "//lib/commons:lang",
-    ],
-)
diff --git a/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java b/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
index 4de436a..d891d6e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
@@ -36,13 +36,8 @@
       public void configure() {
         deleteOnCollection(BRANCH_KIND)
             .toInstance(
-                new RestCollectionModifyView<ProjectResource, BranchResource, Object>() {
-                  @Override
-                  public Object apply(ProjectResource parentResource, Object input)
-                      throws Exception {
-                    return Response.none();
-                  }
-                });
+                (RestCollectionModifyView<ProjectResource, BranchResource, Object>)
+                    (parentResource, input) -> Response.none());
       }
     };
   }
diff --git a/javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
similarity index 90%
rename from javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
index b0adba7..7f55744 100644
--- a/javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
@@ -12,15 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.PUT;
+import static com.google.gerrit.acceptance.rest.util.RestApiCallHelper.execute;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.PUT;
 import static com.google.gerrit.gpg.testing.TestKeys.validKeyWithoutExpiration;
 import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.extensions.common.ChangeInput;
 import com.google.gerrit.gpg.testing.TestKey;
 import com.google.gerrit.server.ServerInitiated;
@@ -34,10 +37,9 @@
  * Tests for checking the bindings of the accounts REST API.
  *
  * <p>These tests only verify that the account REST endpoints are correctly bound, they do no test
- * the functionality of the account REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the account REST endpoints.
  */
-public class AccountsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class AccountsRestApiBindingsIT extends AbstractDaemonTest {
   @Inject private @ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider;
 
   /**
@@ -143,12 +145,12 @@
 
   @Test
   public void accountEndpoints() throws Exception {
-    execute(ACCOUNT_ENDPOINTS, "self");
+    execute(adminRestSession, ACCOUNT_ENDPOINTS, "self");
   }
 
   @Test
   public void emailEndpoints() throws Exception {
-    execute(EMAIL_ENDPOINTS, "self", admin.email);
+    execute(adminRestSession, EMAIL_ENDPOINTS, "self", admin.email);
   }
 
   @Test
@@ -172,20 +174,20 @@
         .self()
         .putGpgKeys(ImmutableList.of(key.getPublicKeyArmored()), ImmutableList.of());
 
-    execute(GPG_KEY_ENDPOINTS, "self", id);
+    execute(adminRestSession, GPG_KEY_ENDPOINTS, "self", id);
   }
 
   @Test
   @UseSsh
   public void sshKeyEndpoints() throws Exception {
     String sshKeySeq = Integer.toString(gApi.accounts().self().listSshKeys().size());
-    execute(SSH_KEY_ENDPOINTS, "self", sshKeySeq);
+    execute(adminRestSession, SSH_KEY_ENDPOINTS, "self", sshKeySeq);
   }
 
   @Test
   public void starEndpoints() throws Exception {
     ChangeInput ci = new ChangeInput(project.get(), "master", "Test change");
     String changeId = gApi.changes().create(ci).get().id;
-    execute(STAR_ENDPOINTS, "self", changeId);
+    execute(adminRestSession, STAR_ENDPOINTS, "self", changeId);
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/BUILD b/javatests/com/google/gerrit/acceptance/rest/binding/BUILD
new file mode 100644
index 0000000..e4242a9
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/BUILD
@@ -0,0 +1,11 @@
+load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests")
+
+acceptance_tests(
+    srcs = glob(["*IT.java"]),
+    group = "rest_bindings",
+    labels = ["rest"],
+    deps = [
+        "//java/com/google/gerrit/server/logging",
+        "//javatests/com/google/gerrit/acceptance/rest/util",
+    ],
+)
diff --git a/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
similarity index 91%
rename from javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
index 59c0903..628b63f 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
@@ -12,16 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
 import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
 import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
 import static java.util.stream.Collectors.toList;
 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
 import com.google.gerrit.extensions.api.changes.DraftInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -43,10 +46,9 @@
  * Tests for checking the bindings of the changes REST API.
  *
  * <p>These tests only verify that the change REST endpoints are correctly bound, they do no test
- * the functionality of the change REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the change REST endpoints.
  */
-public class ChangesRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ChangesRestApiBindingsIT extends AbstractDaemonTest {
   /**
    * Change REST endpoints to be tested, each URL contains a placeholder for the change identifier.
    */
@@ -279,7 +281,7 @@
   public void changeEndpoints() throws Exception {
     String changeId = createChange().getChangeId();
     gApi.changes().id(changeId).edit().create();
-    execute(CHANGE_ENDPOINTS, changeId);
+    RestApiCallHelper.execute(adminRestSession, CHANGE_ENDPOINTS, changeId);
   }
 
   @Test
@@ -287,7 +289,7 @@
     assume().that(notesMigration.readChanges()).isTrue();
 
     String changeId = createChange().getChangeId();
-    execute(CHANGE_ENDPOINTS_NOTEDB, changeId);
+    RestApiCallHelper.execute(adminRestSession, CHANGE_ENDPOINTS_NOTEDB, changeId);
   }
 
   @Test
@@ -297,7 +299,8 @@
     AddReviewerInput addReviewerInput = new AddReviewerInput();
     addReviewerInput.reviewer = user.email;
 
-    execute(
+    RestApiCallHelper.execute(
+        adminRestSession,
         REVIEWER_ENDPOINTS,
         () -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
         changeId,
@@ -308,7 +311,8 @@
   public void voteEndpoints() throws Exception {
     String changeId = createChange().getChangeId();
 
-    execute(
+    RestApiCallHelper.execute(
+        adminRestSession,
         VOTE_ENDPOINTS,
         () -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
         changeId,
@@ -319,7 +323,7 @@
   @Test
   public void revisionEndpoints() throws Exception {
     String changeId = createChange().getChangeId();
-    execute(REVISION_ENDPOINTS, changeId, "current");
+    RestApiCallHelper.execute(adminRestSession, REVISION_ENDPOINTS, changeId, "current");
   }
 
   @Test
@@ -329,7 +333,8 @@
     AddReviewerInput addReviewerInput = new AddReviewerInput();
     addReviewerInput.reviewer = user.email;
 
-    execute(
+    RestApiCallHelper.execute(
+        adminRestSession,
         REVISION_REVIEWER_ENDPOINTS,
         () -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
         changeId,
@@ -341,7 +346,8 @@
   public void revisionVoteEndpoints() throws Exception {
     String changeId = createChange().getChangeId();
 
-    execute(
+    RestApiCallHelper.execute(
+        adminRestSession,
         REVISION_VOTE_ENDPOINTS,
         () -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
         changeId,
@@ -362,7 +368,7 @@
       draftInput.message = "draft comment";
       CommentInfo draftInfo = gApi.changes().id(changeId).current().createDraft(draftInput).get();
 
-      execute(restCall, changeId, "current", draftInfo.id);
+      RestApiCallHelper.execute(adminRestSession, restCall, changeId, "current", draftInfo.id);
     }
   }
 
@@ -382,7 +388,7 @@
       reviewInput.drafts = DraftHandling.PUBLISH;
       gApi.changes().id(changeId).current().review(reviewInput);
 
-      execute(restCall, changeId, "current", commentInfo.id);
+      RestApiCallHelper.execute(adminRestSession, restCall, changeId, "current", commentInfo.id);
     }
   }
 
@@ -409,7 +415,8 @@
         gApi.changes().id(changeId).current().robotCommentsAsList();
     RobotCommentInfo robotCommentInfo = Iterables.getOnlyElement(robotCommentInfos);
 
-    execute(ROBOT_COMMENT_ENDPOINTS, changeId, "current", robotCommentInfo.id);
+    RestApiCallHelper.execute(
+        adminRestSession, ROBOT_COMMENT_ENDPOINTS, changeId, "current", robotCommentInfo.id);
   }
 
   @Test
@@ -449,13 +456,14 @@
     List<String> fixIds = getFixIds(robotCommentInfos);
     String fixId = Iterables.getOnlyElement(fixIds);
 
-    execute(FIX_ENDPOINTS, changeId, "current", fixId);
+    RestApiCallHelper.execute(adminRestSession, FIX_ENDPOINTS, changeId, "current", fixId);
   }
 
   @Test
   public void revisionFileEndpoints() throws Exception {
     String changeId = createChange("Subject", FILENAME, "content").getChangeId();
-    execute(REVISION_FILE_ENDPOINTS, changeId, "current", FILENAME);
+    RestApiCallHelper.execute(
+        adminRestSession, REVISION_FILE_ENDPOINTS, changeId, "current", FILENAME);
   }
 
   @Test
@@ -465,7 +473,8 @@
     // A change message is created on change creation.
     String changeMessageId = Iterables.getOnlyElement(gApi.changes().id(changeId).messages()).id;
 
-    execute(CHANGE_MESSAGE_ENDPOINTS, changeId, changeMessageId);
+    RestApiCallHelper.execute(
+        adminRestSession, CHANGE_MESSAGE_ENDPOINTS, changeId, changeMessageId);
   }
 
   @Test
@@ -473,7 +482,8 @@
     String changeId = createChange("Subject", FILENAME, "content").getChangeId();
 
     // Each of the REST calls creates the change edit newly.
-    execute(
+    RestApiCallHelper.execute(
+        adminRestSession,
         CHANGE_EDIT_CREATE_ENDPOINTS,
         () -> adminRestSession.delete("/changes/" + changeId + "/edit"),
         changeId,
@@ -484,7 +494,7 @@
   public void changeEditEndpoints() throws Exception {
     String changeId = createChange("Subject", FILENAME, "content").getChangeId();
     gApi.changes().id(changeId).edit().create();
-    execute(CHANGE_EDIT_ENDPOINTS, changeId, FILENAME);
+    RestApiCallHelper.execute(adminRestSession, CHANGE_EDIT_ENDPOINTS, changeId, FILENAME);
   }
 
   private static Comment.Range createRange(
diff --git a/javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
similarity index 87%
rename from javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
index 508d407..f187094 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
@@ -12,13 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
 import static com.google.common.truth.Truth8.assertThat;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.server.project.ProjectCacheImpl;
 import com.google.gerrit.server.restapi.config.ListTasks.TaskInfo;
@@ -31,10 +34,9 @@
  * Tests for checking the bindings of the config REST API.
  *
  * <p>These tests only verify that the config REST endpoints are correctly bound, they do no test
- * the functionality of the config REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the config REST endpoints.
  */
-public class ConfigRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ConfigRestApiBindingsIT extends AbstractDaemonTest {
   /**
    * Config REST endpoints to be tested, the URLs contain no placeholders since the only supported
    * config identifier ('server') can be hard-coded.
@@ -83,12 +85,12 @@
     // 'Access Database' is needed for the '/config/server/check.consistency' REST endpoint
     allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
 
-    execute(CONFIG_ENDPOINTS);
+    RestApiCallHelper.execute(adminRestSession, CONFIG_ENDPOINTS);
   }
 
   @Test
   public void cacheEndpoints() throws Exception {
-    execute(CACHE_ENDPOINTS, ProjectCacheImpl.CACHE_NAME);
+    RestApiCallHelper.execute(adminRestSession, CACHE_ENDPOINTS, ProjectCacheImpl.CACHE_NAME);
   }
 
   @Test
@@ -106,6 +108,6 @@
             .findFirst();
     assertThat(id).isPresent();
 
-    execute(TASK_ENDPOINTS, id.get());
+    RestApiCallHelper.execute(adminRestSession, TASK_ENDPOINTS, id.get());
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
similarity index 85%
rename from javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
index 4538f75..b37bb01 100644
--- a/javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
@@ -12,19 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import org.junit.Test;
 
 /**
  * Tests for checking the bindings of the groups REST API.
  *
  * <p>These tests only verify that the group REST endpoints are correctly bound, they do no test the
- * functionality of the group REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * functionality of the group REST endpoints.
  */
-public class GroupsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class GroupsRestApiBindingsIT extends AbstractDaemonTest {
   /**
    * Group REST endpoints to be tested, each URL contains a placeholder for the group identifier.
    */
@@ -80,14 +82,14 @@
   @Test
   public void groupEndpoints() throws Exception {
     String group = gApi.groups().create("test-group").get().name;
-    execute(GROUP_ENDPOINTS, group);
+    RestApiCallHelper.execute(adminRestSession, GROUP_ENDPOINTS, group);
   }
 
   @Test
   public void memberEndpoints() throws Exception {
     String group = gApi.groups().create("test-group").get().name;
     gApi.groups().id(group).addMembers(admin.email);
-    execute(MEMBER_ENDPOINTS, group, admin.email);
+    RestApiCallHelper.execute(adminRestSession, MEMBER_ENDPOINTS, group, admin.email);
   }
 
   @Test
@@ -95,6 +97,6 @@
     String group = gApi.groups().create("test-group").get().name;
     String subgroup = gApi.groups().create("test-subgroup").get().name;
     gApi.groups().id(group).addGroups(subgroup);
-    execute(SUBGROUP_ENDPOINTS, group, subgroup);
+    RestApiCallHelper.execute(adminRestSession, SUBGROUP_ENDPOINTS, group, subgroup);
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
similarity index 85%
rename from javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
index 07ea3d0..5616ebc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
@@ -12,12 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.extensions.api.plugins.InstallPluginInput;
 import com.google.gerrit.extensions.restapi.RawInput;
@@ -27,10 +30,9 @@
  * Tests for checking the bindings of the plugins REST API.
  *
  * <p>These tests only verify that the plugin REST endpoints are correctly bound, they do no test
- * the functionality of the plugin REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the plugin REST endpoints.
  */
-public class PluginsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class PluginsRestApiBindingsIT extends AbstractDaemonTest {
   /**
    * Plugin REST endpoints to be tested, each URL contains a placeholder for the plugin identifier.
    */
@@ -57,7 +59,7 @@
   public void pluginEndpoints() throws Exception {
     String pluginName = "my-plugin";
     installPlugin(pluginName);
-    execute(PLUGIN_ENDPOINTS, pluginName);
+    RestApiCallHelper.execute(adminRestSession, PLUGIN_ENDPOINTS, pluginName);
   }
 
   private void installPlugin(String pluginName) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
similarity index 87%
rename from javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
index ca8d3ce..0c18dbb 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
@@ -12,18 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
 import static com.google.gerrit.acceptance.GitUtil.assertPushOk;
 import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
 import static com.google.gerrit.reviewdb.client.RefNames.REFS_DASHBOARDS;
 import static com.google.gerrit.server.restapi.project.DashboardsCollection.DEFAULT_DASHBOARD_NAME;
 import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GitUtil;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.projects.BranchInput;
@@ -39,10 +42,9 @@
  * Tests for checking the bindings of the projects REST API.
  *
  * <p>These tests only verify that the project REST endpoints are correctly bound, they do no test
- * the functionality of the project REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the project REST endpoints.
  */
-public class ProjectsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ProjectsRestApiBindingsIT extends AbstractDaemonTest {
   private static final ImmutableList<RestCall> PROJECT_ENDPOINTS =
       ImmutableList.of(
           RestCall.get("/projects/%s"),
@@ -157,49 +159,53 @@
 
   @Test
   public void projectEndpoints() throws Exception {
-    execute(PROJECT_ENDPOINTS, project.get());
+    RestApiCallHelper.execute(adminRestSession, PROJECT_ENDPOINTS, project.get());
   }
 
   @Test
   public void childProjectEndpoints() throws Exception {
     Project.NameKey childProject = createProject("test-child-repo", project);
-    execute(CHILD_PROJECT_ENDPOINTS, project.get(), childProject.get());
+    RestApiCallHelper.execute(
+        adminRestSession, CHILD_PROJECT_ENDPOINTS, project.get(), childProject.get());
   }
 
   @Test
   public void branchEndpoints() throws Exception {
-    execute(BRANCH_ENDPOINTS, project.get(), "master");
+    RestApiCallHelper.execute(adminRestSession, BRANCH_ENDPOINTS, project.get(), "master");
   }
 
   @Test
   public void branchFileEndpoints() throws Exception {
     createAndSubmitChange(FILENAME);
-    execute(BRANCH_FILE_ENDPOINTS, project.get(), "master", FILENAME);
+    RestApiCallHelper.execute(
+        adminRestSession, BRANCH_FILE_ENDPOINTS, project.get(), "master", FILENAME);
   }
 
   @Test
   public void dashboardEndpoints() throws Exception {
     createDefaultDashboard();
-    execute(DASHBOARD_ENDPOINTS, project.get(), DEFAULT_DASHBOARD_NAME);
+    RestApiCallHelper.execute(
+        adminRestSession, DASHBOARD_ENDPOINTS, project.get(), DEFAULT_DASHBOARD_NAME);
   }
 
   @Test
   public void tagEndpoints() throws Exception {
     String tag = "test-tag";
     gApi.projects().name(project.get()).tag(tag).create(new TagInput());
-    execute(TAG_ENDPOINTS, project.get(), tag);
+    RestApiCallHelper.execute(adminRestSession, TAG_ENDPOINTS, project.get(), tag);
   }
 
   @Test
   public void commitEndpoints() throws Exception {
     String commit = createAndSubmitChange(FILENAME);
-    execute(COMMIT_ENDPOINTS, project.get(), commit);
+    RestApiCallHelper.execute(adminRestSession, COMMIT_ENDPOINTS, project.get(), commit);
   }
 
   @Test
   public void commitFileEndpoints() throws Exception {
     String commit = createAndSubmitChange(FILENAME);
-    execute(COMMIT_FILE_ENDPOINTS, project.get(), commit, FILENAME);
+    RestApiCallHelper.execute(
+        adminRestSession, COMMIT_FILE_ENDPOINTS, project.get(), commit, FILENAME);
   }
 
   private String createAndSubmitChange(String filename) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
similarity index 79%
rename from javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
index a2c4ea6..6d140c6 100644
--- a/javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
@@ -12,23 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
 
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestApiCallHelper.execute;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.rest.util.RestCall;
 import org.junit.Test;
 
 /**
  * Tests for checking the bindings of the root REST API.
  *
  * <p>These tests only verify that the root REST endpoints are correctly bound, they do no test the
- * functionality of the root REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * functionality of the root REST endpoints.
  */
-public class RootCollectionsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class RootCollectionsRestApiBindingsIT extends AbstractDaemonTest {
   /** Root REST endpoints to be tested, the URLs contain no placeholders. */
   private static final ImmutableList<RestCall> ROOT_ENDPOINTS =
       ImmutableList.of(
@@ -51,6 +53,6 @@
   @Test
   @GerritConfig(name = "plugins.allowRemoteAdmin", value = "true")
   public void rootEndpoints() throws Exception {
-    execute(ROOT_ENDPOINTS);
+    execute(adminRestSession, ROOT_ENDPOINTS);
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/BUILD b/javatests/com/google/gerrit/acceptance/rest/util/BUILD
new file mode 100644
index 0000000..115ea09
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/BUILD
@@ -0,0 +1,10 @@
+java_library(
+    name = "util",
+    testonly = 1,
+    srcs = glob(["*.java"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        "//java/com/google/gerrit/acceptance:lib",
+        "//lib/commons:lang",
+    ],
+)
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
new file mode 100644
index 0000000..52e72fe
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
@@ -0,0 +1,104 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.util;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.Truth.assert_;
+import static org.apache.http.HttpStatus.SC_FORBIDDEN;
+import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
+import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
+import static org.apache.http.HttpStatus.SC_NOT_FOUND;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.RestSession;
+import java.util.List;
+import org.junit.Ignore;
+
+/** Helper to execute REST API calls using the HTTP client. */
+@Ignore
+public class RestApiCallHelper {
+  /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+  public static void execute(RestSession restSession, List<RestCall> restCalls, String... args)
+      throws Exception {
+    execute(restSession, restCalls, () -> {}, args);
+  }
+
+  /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+  public static void execute(
+      RestSession restSession,
+      List<RestCall> restCalls,
+      BeforeRestCall beforeRestCall,
+      String... args)
+      throws Exception {
+    for (RestCall restCall : restCalls) {
+      beforeRestCall.run();
+      execute(restSession, restCall, args);
+    }
+  }
+
+  /**
+   * This method sends a request to a given REST endpoint and verifies that an implementation is
+   * found (no '404 Not Found' response) and that the request doesn't fail (no '500 Internal Server
+   * Error' response). It doesn't verify that the REST endpoint works correctly. This is okay since
+   * the purpose of the test is only to verify that the REST endpoint implementations are correctly
+   * bound.
+   */
+  public static void execute(RestSession restSession, RestCall restCall, String... args)
+      throws Exception {
+    String method = restCall.httpMethod().name();
+    String uri = restCall.uri(args);
+
+    RestResponse response;
+    switch (restCall.httpMethod()) {
+      case GET:
+        response = restSession.get(uri);
+        break;
+      case PUT:
+        response = restSession.put(uri);
+        break;
+      case POST:
+        response = restSession.post(uri);
+        break;
+      case DELETE:
+        response = restSession.delete(uri);
+        break;
+      default:
+        assert_().fail(String.format("unsupported method: %s", restCall.httpMethod().name()));
+        throw new IllegalStateException();
+    }
+
+    int status = response.getStatusCode();
+    String body = response.hasContent() ? response.getEntityContent() : "";
+
+    String msg = String.format("%s %s returned %d: %s", method, uri, status, body);
+    if (restCall.expectedResponseCode().isPresent()) {
+      assertWithMessage(msg).that(status).isEqualTo(restCall.expectedResponseCode().get());
+      if (restCall.expectedMessage().isPresent()) {
+        assertWithMessage(msg).that(body).contains(restCall.expectedMessage().get());
+      }
+    } else {
+      assertWithMessage(msg)
+          .that(status)
+          .isNotIn(ImmutableList.of(SC_FORBIDDEN, SC_NOT_FOUND, SC_METHOD_NOT_ALLOWED));
+      assertWithMessage(msg).that(status).isLessThan(SC_INTERNAL_SERVER_ERROR);
+    }
+  }
+
+  @FunctionalInterface
+  public interface BeforeRestCall {
+    void run() throws Exception;
+  }
+}
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java b/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java
new file mode 100644
index 0000000..a322089
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java
@@ -0,0 +1,88 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.util;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.auto.value.AutoValue;
+import java.util.Optional;
+import jdk.nashorn.internal.ir.annotations.Ignore;
+import org.apache.commons.lang.StringUtils;
+
+/** Data container for test REST requests. */
+@Ignore
+@AutoValue
+public abstract class RestCall {
+  public enum Method {
+    GET,
+    PUT,
+    POST,
+    DELETE
+  }
+
+  public static RestCall get(String uriFormat) {
+    return builder(Method.GET, uriFormat).build();
+  }
+
+  public static RestCall put(String uriFormat) {
+    return builder(Method.PUT, uriFormat).build();
+  }
+
+  public static RestCall post(String uriFormat) {
+    return builder(Method.POST, uriFormat).build();
+  }
+
+  public static RestCall delete(String uriFormat) {
+    return builder(Method.DELETE, uriFormat).build();
+  }
+
+  public static Builder builder(Method httpMethod, String uriFormat) {
+    return new AutoValue_RestCall.Builder().httpMethod(httpMethod).uriFormat(uriFormat);
+  }
+
+  public abstract Method httpMethod();
+
+  public abstract String uriFormat();
+
+  public abstract Optional<Integer> expectedResponseCode();
+
+  public abstract Optional<String> expectedMessage();
+
+  public String uri(String... args) {
+    String uriFormat = uriFormat();
+    int expectedArgNum = StringUtils.countMatches(uriFormat, "%s");
+    checkState(
+        args.length == expectedArgNum,
+        "uriFormat %s needs %s arguments, got only %s: %s",
+        uriFormat,
+        expectedArgNum,
+        args.length,
+        args);
+    return String.format(uriFormat, (Object[]) args);
+  }
+
+  @AutoValue.Builder
+  public abstract static class Builder {
+    public abstract Builder httpMethod(Method httpMethod);
+
+    public abstract Builder uriFormat(String uriFormat);
+
+    public abstract Builder expectedResponseCode(int expectedResponseCode);
+
+    public abstract Builder expectedMessage(String expectedMessage);
+
+    public abstract RestCall build();
+  }
+}
diff --git a/javatests/com/google/gerrit/common/AutoValueTest.java b/javatests/com/google/gerrit/common/AutoValueTest.java
index 947fe4a..89d7bf4 100644
--- a/javatests/com/google/gerrit/common/AutoValueTest.java
+++ b/javatests/com/google/gerrit/common/AutoValueTest.java
@@ -17,9 +17,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.auto.value.AutoValue;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class AutoValueTest {
+public class AutoValueTest extends GerritBaseTests {
   @AutoValue
   abstract static class Auto {
     static Auto create(String val) {
diff --git a/javatests/com/google/gerrit/common/BUILD b/javatests/com/google/gerrit/common/BUILD
index 9c5700e..88ddcd5 100644
--- a/javatests/com/google/gerrit/common/BUILD
+++ b/javatests/com/google/gerrit/common/BUILD
@@ -12,6 +12,7 @@
         "//java/com/google/gerrit/common:version",
         "//java/com/google/gerrit/launcher",
         "//java/com/google/gerrit/reviewdb:server",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
diff --git a/javatests/com/google/gerrit/common/data/AccessSectionTest.java b/javatests/com/google/gerrit/common/data/AccessSectionTest.java
index a59c015..b12a9c2 100644
--- a/javatests/com/google/gerrit/common/data/AccessSectionTest.java
+++ b/javatests/com/google/gerrit/common/data/AccessSectionTest.java
@@ -17,17 +17,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class AccessSectionTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class AccessSectionTest extends GerritBaseTests {
   private static final String REF_PATTERN = "refs/heads/master";
 
   private AccessSection accessSection;
diff --git a/javatests/com/google/gerrit/common/data/EncodePathSeparatorTest.java b/javatests/com/google/gerrit/common/data/EncodePathSeparatorTest.java
index dcd3c05..3dd2db3 100644
--- a/javatests/com/google/gerrit/common/data/EncodePathSeparatorTest.java
+++ b/javatests/com/google/gerrit/common/data/EncodePathSeparatorTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class EncodePathSeparatorTest {
+public class EncodePathSeparatorTest extends GerritBaseTests {
   @Test
   public void defaultBehaviour() {
     assertThat(new GitwebType().replacePathSeparator("a/b")).isEqualTo("a/b");
diff --git a/javatests/com/google/gerrit/common/data/FilenameComparatorTest.java b/javatests/com/google/gerrit/common/data/FilenameComparatorTest.java
index ec71e05..055f57d 100644
--- a/javatests/com/google/gerrit/common/data/FilenameComparatorTest.java
+++ b/javatests/com/google/gerrit/common/data/FilenameComparatorTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class FilenameComparatorTest {
+public class FilenameComparatorTest extends GerritBaseTests {
   private FilenameComparator comparator = FilenameComparator.INSTANCE;
 
   @Test
diff --git a/javatests/com/google/gerrit/common/data/GroupReferenceTest.java b/javatests/com/google/gerrit/common/data/GroupReferenceTest.java
index fdc9dc6..8cf486b 100644
--- a/javatests/com/google/gerrit/common/data/GroupReferenceTest.java
+++ b/javatests/com/google/gerrit/common/data/GroupReferenceTest.java
@@ -18,13 +18,10 @@
 
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
-import org.junit.Rule;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class GroupReferenceTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class GroupReferenceTest extends GerritBaseTests {
   @Test
   public void forGroupDescription() {
     String name = "foo";
diff --git a/javatests/com/google/gerrit/common/data/LabelFunctionTest.java b/javatests/com/google/gerrit/common/data/LabelFunctionTest.java
index 985f514..ef71b67 100644
--- a/javatests/com/google/gerrit/common/data/LabelFunctionTest.java
+++ b/javatests/com/google/gerrit/common/data/LabelFunctionTest.java
@@ -23,13 +23,14 @@
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.PatchSet.Id;
 import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.sql.Date;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 import org.junit.Test;
 
-public class LabelFunctionTest {
+public class LabelFunctionTest extends GerritBaseTests {
   private static final String LABEL_NAME = "Verified";
   private static final LabelId LABEL_ID = new LabelId(LABEL_NAME);
   private static final Change.Id CHANGE_ID = new Change.Id(100);
diff --git a/javatests/com/google/gerrit/common/data/LabelTypeTest.java b/javatests/com/google/gerrit/common/data/LabelTypeTest.java
index 6c3befb..db0df2e 100644
--- a/javatests/com/google/gerrit/common/data/LabelTypeTest.java
+++ b/javatests/com/google/gerrit/common/data/LabelTypeTest.java
@@ -17,9 +17,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class LabelTypeTest {
+public class LabelTypeTest extends GerritBaseTests {
   @Test
   public void sortLabelValues() {
     LabelValue v0 = new LabelValue((short) 0, "Zero");
diff --git a/javatests/com/google/gerrit/common/data/ParameterizedStringTest.java b/javatests/com/google/gerrit/common/data/ParameterizedStringTest.java
index b646d2b..b22a511 100644
--- a/javatests/com/google/gerrit/common/data/ParameterizedStringTest.java
+++ b/javatests/com/google/gerrit/common/data/ParameterizedStringTest.java
@@ -17,11 +17,12 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.HashMap;
 import java.util.Map;
 import org.junit.Test;
 
-public class ParameterizedStringTest {
+public class ParameterizedStringTest extends GerritBaseTests {
   @Test
   public void emptyString() {
     ParameterizedString p = new ParameterizedString("");
diff --git a/javatests/com/google/gerrit/common/data/PermissionRuleTest.java b/javatests/com/google/gerrit/common/data/PermissionRuleTest.java
index 14c47b4..f442f39 100644
--- a/javatests/com/google/gerrit/common/data/PermissionRuleTest.java
+++ b/javatests/com/google/gerrit/common/data/PermissionRuleTest.java
@@ -18,14 +18,11 @@
 
 import com.google.gerrit.common.data.PermissionRule.Action;
 import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class PermissionRuleTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class PermissionRuleTest extends GerritBaseTests {
   private GroupReference groupReference;
   private PermissionRule permissionRule;
 
diff --git a/javatests/com/google/gerrit/common/data/PermissionTest.java b/javatests/com/google/gerrit/common/data/PermissionTest.java
index f76323f..84fb2f0 100644
--- a/javatests/com/google/gerrit/common/data/PermissionTest.java
+++ b/javatests/com/google/gerrit/common/data/PermissionTest.java
@@ -18,12 +18,13 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 
-public class PermissionTest {
+public class PermissionTest extends GerritBaseTests {
   private static final String PERMISSION_NAME = "foo";
 
   private Permission permission;
diff --git a/javatests/com/google/gerrit/common/data/SubmitRecordTest.java b/javatests/com/google/gerrit/common/data/SubmitRecordTest.java
index 5386b87..5b9fde7 100644
--- a/javatests/com/google/gerrit/common/data/SubmitRecordTest.java
+++ b/javatests/com/google/gerrit/common/data/SubmitRecordTest.java
@@ -16,11 +16,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.Collection;
 import org.junit.Test;
 
-public class SubmitRecordTest {
+public class SubmitRecordTest extends GerritBaseTests {
   private static final SubmitRecord OK_RECORD;
   private static final SubmitRecord FORCED_RECORD;
   private static final SubmitRecord NOT_READY_RECORD;
diff --git a/javatests/com/google/gerrit/elasticsearch/BUILD b/javatests/com/google/gerrit/elasticsearch/BUILD
index cc849eb..51d45f2 100644
--- a/javatests/com/google/gerrit/elasticsearch/BUILD
+++ b/javatests/com/google/gerrit/elasticsearch/BUILD
@@ -86,6 +86,7 @@
     tags = ["elastic"],
     deps = [
         "//java/com/google/gerrit/elasticsearch",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/guice",
         "//lib/jgit/org.eclipse.jgit:jgit",
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
index 559b8c7..735354e 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
@@ -27,17 +27,14 @@
 import static java.util.stream.Collectors.toList;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.ProvisionException;
 import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.lib.Config;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class ElasticConfigurationTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class ElasticConfigurationTest extends GerritBaseTests {
   @Test
   public void singleServerNoOtherConfig() throws Exception {
     Config cfg = newConfig();
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
index b598a0a..3ab9d5a 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
@@ -16,13 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import org.junit.Rule;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class ElasticVersionTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class ElasticVersionTest extends GerritBaseTests {
   @Test
   public void supportedVersion() throws Exception {
     assertThat(ElasticVersion.forVersion("2.4.0")).isEqualTo(ElasticVersion.V2_4);
diff --git a/javatests/com/google/gerrit/extensions/BUILD b/javatests/com/google/gerrit/extensions/BUILD
index 069c915..adf696d 100644
--- a/javatests/com/google/gerrit/extensions/BUILD
+++ b/javatests/com/google/gerrit/extensions/BUILD
@@ -7,6 +7,7 @@
     deps = [
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/extensions/common/testing:common-test-util",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/guice",
         "//lib/truth",
     ],
diff --git a/javatests/com/google/gerrit/extensions/api/lfs/LfsDefinitionsTest.java b/javatests/com/google/gerrit/extensions/api/lfs/LfsDefinitionsTest.java
index 0be10ee..86dce04 100644
--- a/javatests/com/google/gerrit/extensions/api/lfs/LfsDefinitionsTest.java
+++ b/javatests/com/google/gerrit/extensions/api/lfs/LfsDefinitionsTest.java
@@ -16,11 +16,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.junit.Test;
 
-public class LfsDefinitionsTest {
+public class LfsDefinitionsTest extends GerritBaseTests {
   private static final String[] URL_PREFIXES = new String[] {"/", "/a/", "/p/", "/a/p/"};
 
   @Test
diff --git a/javatests/com/google/gerrit/extensions/client/RangeTest.java b/javatests/com/google/gerrit/extensions/client/RangeTest.java
index b8938aa..2c713b5 100644
--- a/javatests/com/google/gerrit/extensions/client/RangeTest.java
+++ b/javatests/com/google/gerrit/extensions/client/RangeTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.gerrit.extensions.common.testing.RangeSubject.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class RangeTest {
+public class RangeTest extends GerritBaseTests {
 
   @Test
   public void rangeOverMultipleLinesWithSmallerEndCharacterIsValid() {
diff --git a/javatests/com/google/gerrit/extensions/conditions/BUILD b/javatests/com/google/gerrit/extensions/conditions/BUILD
index e2d5951..7ad2ad3 100644
--- a/javatests/com/google/gerrit/extensions/conditions/BUILD
+++ b/javatests/com/google/gerrit/extensions/conditions/BUILD
@@ -5,6 +5,7 @@
     srcs = glob(["*.java"]),
     deps = [
         "//java/com/google/gerrit/extensions:lib",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/truth",
     ],
 )
diff --git a/javatests/com/google/gerrit/extensions/conditions/BooleanConditionTest.java b/javatests/com/google/gerrit/extensions/conditions/BooleanConditionTest.java
index f9f1fa85..81cb719 100644
--- a/javatests/com/google/gerrit/extensions/conditions/BooleanConditionTest.java
+++ b/javatests/com/google/gerrit/extensions/conditions/BooleanConditionTest.java
@@ -20,9 +20,10 @@
 import static com.google.gerrit.extensions.conditions.BooleanCondition.valueOf;
 import static org.junit.Assert.assertEquals;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class BooleanConditionTest {
+public class BooleanConditionTest extends GerritBaseTests {
 
   private static final BooleanCondition NO_TRIVIAL_EVALUATION =
       new BooleanCondition() {
diff --git a/javatests/com/google/gerrit/extensions/registration/DynamicSetTest.java b/javatests/com/google/gerrit/extensions/registration/DynamicSetTest.java
index 0542c35..d950224 100644
--- a/javatests/com/google/gerrit/extensions/registration/DynamicSetTest.java
+++ b/javatests/com/google/gerrit/extensions/registration/DynamicSetTest.java
@@ -17,13 +17,14 @@
 import static com.google.common.truth.Truth.assertThat;
 import static java.util.stream.Collectors.toSet;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.util.Providers;
 import java.util.Iterator;
 import org.junit.Test;
 
-public class DynamicSetTest {
+public class DynamicSetTest extends GerritBaseTests {
   // In tests for {@link DynamicSet#contains(Object)}, be sure to avoid
   // {@code assertThat(ds).contains(...) @} and
   // {@code assertThat(ds).DoesNotContains(...) @} as (since
diff --git a/javatests/com/google/gerrit/git/BUILD b/javatests/com/google/gerrit/git/BUILD
index 458bdf9..d57d73f 100644
--- a/javatests/com/google/gerrit/git/BUILD
+++ b/javatests/com/google/gerrit/git/BUILD
@@ -10,6 +10,7 @@
     tags = ["no_windows"],
     deps = [
         "//java/com/google/gerrit/git",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib:junit",
         "//lib/jgit/org.eclipse.jgit:jgit",
@@ -27,6 +28,7 @@
     ),
     deps = [
         "//java/com/google/gerrit/git",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/jgit/org.eclipse.jgit:jgit",
         "//lib/truth",
diff --git a/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java b/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java
index 99247b8..cdc94c2 100644
--- a/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java
+++ b/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.MoreFiles;
 import com.google.common.io.RecursiveDeleteOption;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
@@ -35,7 +36,7 @@
 import org.junit.runners.Parameterized.Parameters;
 
 @RunWith(Parameterized.class)
-public class RefUpdateUtilRepoTest {
+public class RefUpdateUtilRepoTest extends GerritBaseTests {
   public enum RepoSetup {
     LOCAL_DISK {
       @Override
diff --git a/javatests/com/google/gerrit/git/RefUpdateUtilTest.java b/javatests/com/google/gerrit/git/RefUpdateUtilTest.java
index fe40fb4..429583a 100644
--- a/javatests/com/google/gerrit/git/RefUpdateUtilTest.java
+++ b/javatests/com/google/gerrit/git/RefUpdateUtilTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assert_;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.IOException;
 import java.util.function.Consumer;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
@@ -32,7 +33,7 @@
 import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
-public class RefUpdateUtilTest {
+public class RefUpdateUtilTest extends GerritBaseTests {
   private static final Consumer<ReceiveCommand> OK = c -> c.setResult(ReceiveCommand.Result.OK);
   private static final Consumer<ReceiveCommand> LOCK_FAILURE =
       c -> c.setResult(ReceiveCommand.Result.LOCK_FAILURE);
diff --git a/javatests/com/google/gerrit/git/testing/BUILD b/javatests/com/google/gerrit/git/testing/BUILD
index 56e9ec2..1309185 100644
--- a/javatests/com/google/gerrit/git/testing/BUILD
+++ b/javatests/com/google/gerrit/git/testing/BUILD
@@ -5,6 +5,7 @@
     srcs = glob(["*.java"]),
     deps = [
         "//java/com/google/gerrit/git/testing",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/truth",
     ],
 )
diff --git a/javatests/com/google/gerrit/git/testing/PushResultSubjectTest.java b/javatests/com/google/gerrit/git/testing/PushResultSubjectTest.java
index 3bf815b..5ab52d4 100644
--- a/javatests/com/google/gerrit/git/testing/PushResultSubjectTest.java
+++ b/javatests/com/google/gerrit/git/testing/PushResultSubjectTest.java
@@ -18,9 +18,10 @@
 import static com.google.gerrit.git.testing.PushResultSubject.parseProcessed;
 import static com.google.gerrit.git.testing.PushResultSubject.trimMessages;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class PushResultSubjectTest {
+public class PushResultSubjectTest extends GerritBaseTests {
   @Test
   public void testTrimMessages() {
     assertThat(trimMessages(null)).isNull();
diff --git a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index 689d786..b90ccf7c 100644
--- a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -44,6 +44,7 @@
 import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryModule;
 import com.google.gerrit.testing.NoteDbMode;
@@ -69,7 +70,7 @@
 import org.junit.Test;
 
 /** Unit tests for {@link GerritPublicKeyChecker}. */
-public class GerritPublicKeyCheckerTest {
+public class GerritPublicKeyCheckerTest extends GerritBaseTests {
   @Inject @ServerInitiated private Provider<AccountsUpdate> accountsUpdateProvider;
 
   @Inject private AccountManager accountManager;
diff --git a/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
index 48d5266..145b9cf 100644
--- a/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
@@ -38,6 +38,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.google.gerrit.gpg.testing.TestKey;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -57,13 +58,9 @@
 import org.eclipse.jgit.lib.RefUpdate;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class PublicKeyCheckerTest {
-  @Rule public ExpectedException thrown = ExpectedException.none();
-
+public class PublicKeyCheckerTest extends GerritBaseTests {
   private InMemoryRepository repo;
   private PublicKeyStore store;
 
diff --git a/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java b/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
index 2fc06a6..95c0e85 100644
--- a/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
+++ b/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
@@ -28,6 +28,7 @@
 
 import com.google.common.collect.Iterators;
 import com.google.gerrit.gpg.testing.TestKey;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -49,7 +50,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class PublicKeyStoreTest {
+public class PublicKeyStoreTest extends GerritBaseTests {
   private TestRepository<?> tr;
   private PublicKeyStore store;
 
diff --git a/javatests/com/google/gerrit/gpg/PushCertificateCheckerTest.java b/javatests/com/google/gerrit/gpg/PushCertificateCheckerTest.java
index 266f868..67bf050 100644
--- a/javatests/com/google/gerrit/gpg/PushCertificateCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/PushCertificateCheckerTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.google.gerrit.gpg.testing.TestKey;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStreamReader;
@@ -53,7 +54,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class PushCertificateCheckerTest {
+public class PushCertificateCheckerTest extends GerritBaseTests {
   private InMemoryRepository repo;
   private PublicKeyStore store;
   private SignedPushConfig signedPushConfig;
diff --git a/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java b/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
index 1c6559b0..e2c58d8 100644
--- a/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
+++ b/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
 import com.google.gerrit.server.plugins.Plugin;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
 import com.google.gerrit.util.http.testutil.FakeHttpServletResponse;
 import com.google.inject.Key;
@@ -35,7 +36,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class AllRequestFilterFilterProxyTest {
+public class AllRequestFilterFilterProxyTest extends GerritBaseTests {
   /**
    * Set of filters for FilterProxy
    *
diff --git a/javatests/com/google/gerrit/httpd/BUILD b/javatests/com/google/gerrit/httpd/BUILD
index ec2df15..fe76d54 100644
--- a/javatests/com/google/gerrit/httpd/BUILD
+++ b/javatests/com/google/gerrit/httpd/BUILD
@@ -10,6 +10,7 @@
         "//java/com/google/gerrit/httpd",
         "//java/com/google/gerrit/reviewdb:server",
         "//java/com/google/gerrit/server",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//java/com/google/gerrit/util/http",
         "//javatests/com/google/gerrit/util/http/testutil",
         "//lib:gson",
diff --git a/javatests/com/google/gerrit/httpd/RemoteUserUtilTest.java b/javatests/com/google/gerrit/httpd/RemoteUserUtilTest.java
index f012ee3..e19085d 100644
--- a/javatests/com/google/gerrit/httpd/RemoteUserUtilTest.java
+++ b/javatests/com/google/gerrit/httpd/RemoteUserUtilTest.java
@@ -17,9 +17,10 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.httpd.RemoteUserUtil.extractUsername;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class RemoteUserUtilTest {
+public class RemoteUserUtilTest extends GerritBaseTests {
   @Test
   public void testExtractUsername() {
     assertThat(extractUsername(null)).isNull();
diff --git a/javatests/com/google/gerrit/httpd/plugins/ContextMapperTest.java b/javatests/com/google/gerrit/httpd/plugins/ContextMapperTest.java
index 684a241..2de3788 100644
--- a/javatests/com/google/gerrit/httpd/plugins/ContextMapperTest.java
+++ b/javatests/com/google/gerrit/httpd/plugins/ContextMapperTest.java
@@ -16,11 +16,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import org.junit.Test;
 
-public class ContextMapperTest {
+public class ContextMapperTest extends GerritBaseTests {
 
   private static final String CONTEXT = "/context";
   private static final String PLUGIN_NAME = "my-plugin";
diff --git a/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java b/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
index 307a23e..b4f8e7a 100644
--- a/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
+++ b/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
@@ -17,11 +17,12 @@
 import static com.google.common.truth.Truth.assertThat;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.template.soy.data.SoyMapData;
 import java.net.URISyntaxException;
 import org.junit.Test;
 
-public class IndexServletTest {
+public class IndexServletTest extends GerritBaseTests {
   static class TestIndexServlet extends IndexServlet {
     private static final long serialVersionUID = 1L;
 
diff --git a/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java b/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
index 6dd15bc..cfcc1d0 100644
--- a/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
+++ b/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
@@ -28,6 +28,7 @@
 import com.google.common.jimfs.Configuration;
 import com.google.common.jimfs.Jimfs;
 import com.google.gerrit.httpd.raw.ResourceServlet.Resource;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
 import com.google.gerrit.util.http.testutil.FakeHttpServletResponse;
 import java.io.ByteArrayInputStream;
@@ -44,7 +45,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class ResourceServletTest {
+public class ResourceServletTest extends GerritBaseTests {
   private static Cache<Path, Resource> newCache(int size) {
     return CacheBuilder.newBuilder().maximumSize(size).recordStats().build();
   }
diff --git a/javatests/com/google/gerrit/httpd/restapi/HttpLogRedactTest.java b/javatests/com/google/gerrit/httpd/restapi/HttpLogRedactTest.java
index fb1ebd9..fa3eaea 100644
--- a/javatests/com/google/gerrit/httpd/restapi/HttpLogRedactTest.java
+++ b/javatests/com/google/gerrit/httpd/restapi/HttpLogRedactTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class HttpLogRedactTest {
+public class HttpLogRedactTest extends GerritBaseTests {
   @Test
   public void redactAuth() {
     assertThat(LogRedactUtil.redactQueryString("query=status:open")).isEqualTo("query=status:open");
diff --git a/javatests/com/google/gerrit/httpd/restapi/ParameterParserTest.java b/javatests/com/google/gerrit/httpd/restapi/ParameterParserTest.java
index 13732b0..30d318b 100644
--- a/javatests/com/google/gerrit/httpd/restapi/ParameterParserTest.java
+++ b/javatests/com/google/gerrit/httpd/restapi/ParameterParserTest.java
@@ -22,13 +22,14 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.httpd.restapi.ParameterParser.QueryParams;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonPrimitive;
 import org.junit.Test;
 
-public class ParameterParserTest {
+public class ParameterParserTest extends GerritBaseTests {
   @Test
   public void convertFormToJson() throws BadRequestException {
     JsonObject obj =
diff --git a/javatests/com/google/gerrit/index/BUILD b/javatests/com/google/gerrit/index/BUILD
index 5597ed1..e3436bc 100644
--- a/javatests/com/google/gerrit/index/BUILD
+++ b/javatests/com/google/gerrit/index/BUILD
@@ -9,6 +9,7 @@
         "//antlr3:query_parser",
         "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/index:query_exception",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib:junit",
         "//lib/antlr:java-runtime",
diff --git a/javatests/com/google/gerrit/index/SchemaUtilTest.java b/javatests/com/google/gerrit/index/SchemaUtilTest.java
index 3c0bbe0..d6b8421 100644
--- a/javatests/com/google/gerrit/index/SchemaUtilTest.java
+++ b/javatests/com/google/gerrit/index/SchemaUtilTest.java
@@ -19,15 +19,12 @@
 import static com.google.gerrit.index.SchemaUtil.getPersonParts;
 import static com.google.gerrit.index.SchemaUtil.schema;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Map;
 import org.eclipse.jgit.lib.PersonIdent;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class SchemaUtilTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class SchemaUtilTest extends GerritBaseTests {
   static class TestSchemas {
     static final Schema<String> V1 = schema();
     static final Schema<String> V2 = schema();
diff --git a/javatests/com/google/gerrit/index/query/PredicateTest.java b/javatests/com/google/gerrit/index/query/PredicateTest.java
index 6979d82..2295a60 100644
--- a/javatests/com/google/gerrit/index/query/PredicateTest.java
+++ b/javatests/com/google/gerrit/index/query/PredicateTest.java
@@ -14,14 +14,11 @@
 
 package com.google.gerrit.index.query;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.rules.ExpectedException;
 
 @Ignore
-public abstract class PredicateTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public abstract class PredicateTest extends GerritBaseTests {
   protected static final class TestPredicate extends OperatorPredicate<String> {
     protected TestPredicate(String name, String value) {
       super(name, value);
diff --git a/javatests/com/google/gerrit/index/query/QueryParserTest.java b/javatests/com/google/gerrit/index/query/QueryParserTest.java
index 448f292..2175f7d 100644
--- a/javatests/com/google/gerrit/index/query/QueryParserTest.java
+++ b/javatests/com/google/gerrit/index/query/QueryParserTest.java
@@ -16,10 +16,11 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.antlr.runtime.tree.Tree;
 import org.junit.Test;
 
-public class QueryParserTest {
+public class QueryParserTest extends GerritBaseTests {
   @Test
   public void projectBare() throws QueryParseException {
     Tree r;
diff --git a/javatests/com/google/gerrit/mail/AbstractParserTest.java b/javatests/com/google/gerrit/mail/AbstractParserTest.java
index 6ab4ca2..c375aff 100644
--- a/javatests/com/google/gerrit/mail/AbstractParserTest.java
+++ b/javatests/com/google/gerrit/mail/AbstractParserTest.java
@@ -18,6 +18,7 @@
 
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Comment;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.sql.Timestamp;
 import java.time.Instant;
 import java.util.ArrayList;
@@ -25,7 +26,7 @@
 import org.junit.Ignore;
 
 @Ignore
-public class AbstractParserTest {
+public class AbstractParserTest extends GerritBaseTests {
   protected static final String CHANGE_URL =
       "https://gerrit-review.googlesource.com/c/project/+/123";
 
diff --git a/javatests/com/google/gerrit/mail/MailHeaderParserTest.java b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
index 2d2c2ea..cdc8d7a 100644
--- a/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
+++ b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
@@ -16,13 +16,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.Month;
 import java.time.ZoneOffset;
 import org.junit.Test;
 
-public class MailHeaderParserTest {
+public class MailHeaderParserTest extends GerritBaseTests {
   @Test
   public void parseMetadataFromHeader() {
     // This tests if the metadata parser is able to parse metadata from the
diff --git a/javatests/com/google/gerrit/mail/ParserUtilTest.java b/javatests/com/google/gerrit/mail/ParserUtilTest.java
index 47a5367..ed40a57 100644
--- a/javatests/com/google/gerrit/mail/ParserUtilTest.java
+++ b/javatests/com/google/gerrit/mail/ParserUtilTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class ParserUtilTest {
+public class ParserUtilTest extends GerritBaseTests {
   @Test
   public void trimQuotationLineOnMessageWithoutQuoatationLine() throws Exception {
     assertThat(ParserUtil.trimQuotation("One line")).isEqualTo("One line");
diff --git a/javatests/com/google/gerrit/metrics/dropwizard/BUILD b/javatests/com/google/gerrit/metrics/dropwizard/BUILD
index 98d12b2..63d4452 100644
--- a/javatests/com/google/gerrit/metrics/dropwizard/BUILD
+++ b/javatests/com/google/gerrit/metrics/dropwizard/BUILD
@@ -7,6 +7,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//java/com/google/gerrit/metrics/dropwizard",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/truth",
     ],
 )
diff --git a/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java b/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
index 9b21bf6..d6bcb62 100644
--- a/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
+++ b/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class DropWizardMetricMakerTest {
+public class DropWizardMetricMakerTest extends GerritBaseTests {
   DropWizardMetricMaker metrics =
       new DropWizardMetricMaker(null /* MetricRegistry unused in tests */);
 
diff --git a/javatests/com/google/gerrit/metrics/proc/BUILD b/javatests/com/google/gerrit/metrics/proc/BUILD
index 91e5cf6..7d8af90 100644
--- a/javatests/com/google/gerrit/metrics/proc/BUILD
+++ b/javatests/com/google/gerrit/metrics/proc/BUILD
@@ -9,6 +9,7 @@
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/metrics",
         "//java/com/google/gerrit/metrics/dropwizard",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/dropwizard:dropwizard-core",
         "//lib/guice",
         "//lib/truth",
diff --git a/javatests/com/google/gerrit/metrics/proc/ProcMetricModuleTest.java b/javatests/com/google/gerrit/metrics/proc/ProcMetricModuleTest.java
index 91b01f6..0a5dabf 100644
--- a/javatests/com/google/gerrit/metrics/proc/ProcMetricModuleTest.java
+++ b/javatests/com/google/gerrit/metrics/proc/ProcMetricModuleTest.java
@@ -30,19 +30,16 @@
 import com.google.gerrit.metrics.Field;
 import com.google.gerrit.metrics.MetricMaker;
 import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class ProcMetricModuleTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class ProcMetricModuleTest extends GerritBaseTests {
   @Inject MetricMaker metrics;
 
   @Inject MetricRegistry registry;
diff --git a/javatests/com/google/gerrit/pgm/init/InitTestCase.java b/javatests/com/google/gerrit/pgm/init/InitTestCase.java
deleted file mode 100644
index 35c0937..0000000
--- a/javatests/com/google/gerrit/pgm/init/InitTestCase.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm.init;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
-import org.junit.Ignore;
-
-@Ignore
-public abstract class InitTestCase extends LocalDiskRepositoryTestCase {
-  protected Path newSitePath() throws IOException {
-    return createWorkRepository().getWorkTree().toPath().resolve("test_site");
-  }
-}
diff --git a/javatests/com/google/gerrit/pgm/init/LibrariesTest.java b/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
index af21ad0..1f42373 100644
--- a/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
+++ b/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
@@ -21,12 +21,13 @@
 
 import com.google.gerrit.pgm.init.api.ConsoleUI;
 import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.Provider;
 import java.nio.file.Paths;
 import java.util.Collections;
 import org.junit.Test;
 
-public class LibrariesTest {
+public class LibrariesTest extends GerritBaseTests {
   @Test
   public void create() throws Exception {
     final SitePaths site = new SitePaths(Paths.get("."));
diff --git a/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java b/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
index 4d3d6df..159ff0d 100644
--- a/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
+++ b/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
@@ -32,6 +32,7 @@
 import com.google.gerrit.pgm.init.api.Section;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.securestore.testing.InMemorySecureStore;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
@@ -40,13 +41,16 @@
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.util.FS;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
-public class UpgradeFrom2_0_xTest extends InitTestCase {
+public class UpgradeFrom2_0_xTest extends GerritBaseTests {
+  @Rule public TemporaryFolder folder = new TemporaryFolder();
 
   @Test
   public void upgrade() throws IOException, ConfigInvalidException {
-    final Path p = newSitePath();
+    final Path p = folder.newFolder().toPath();
     final SitePaths site = new SitePaths(p);
     assertTrue(site.isNew);
     FileUtil.mkdirsOrDie(site.etc_dir, "Failed to create");
diff --git a/javatests/com/google/gerrit/pgm/init/api/AllProjectsConfigTest.java b/javatests/com/google/gerrit/pgm/init/api/AllProjectsConfigTest.java
index 68b4a8e..326e996 100644
--- a/javatests/com/google/gerrit/pgm/init/api/AllProjectsConfigTest.java
+++ b/javatests/com/google/gerrit/pgm/init/api/AllProjectsConfigTest.java
@@ -21,7 +21,6 @@
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.securestore.testing.InMemorySecureStore;
-import com.google.gerrit.testing.TempFileUtil;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -34,20 +33,23 @@
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.util.FS;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 public class AllProjectsConfigTest {
   private static final String ALL_PROJECTS = "All-The-Projects";
 
+  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   private SitePaths sitePaths;
   private AllProjectsConfig allProjectsConfig;
   private File allProjectsRepoFile;
 
   @Before
   public void setUp() throws Exception {
-    sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
+    sitePaths = new SitePaths(temporaryFolder.newFolder().toPath());
     Files.createDirectories(sitePaths.etc_dir);
 
     Path gitPath = sitePaths.resolve("git");
@@ -76,11 +78,6 @@
         new AllProjectsConfig(new AllProjectsNameOnInitProvider(sections), sitePaths, flags);
   }
 
-  @After
-  public void tearDown() throws Exception {
-    TempFileUtil.cleanup();
-  }
-
   @Test
   public void noBaseConfig() throws Exception {
     assertThat(getConfig().getString("foo", null, "bar")).isNull();
diff --git a/javatests/com/google/gerrit/proto/BUILD b/javatests/com/google/gerrit/proto/BUILD
index 0940f6b..a249638 100644
--- a/javatests/com/google/gerrit/proto/BUILD
+++ b/javatests/com/google/gerrit/proto/BUILD
@@ -4,6 +4,7 @@
     name = "proto_tests",
     srcs = glob(["*.java"]),
     deps = [
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/truth:truth-proto-extension",
         "//proto:reviewdb_java_proto",
 
diff --git a/javatests/com/google/gerrit/proto/ReviewDbProtoTest.java b/javatests/com/google/gerrit/proto/ReviewDbProtoTest.java
index 49cd2921..d6ffee5 100644
--- a/javatests/com/google/gerrit/proto/ReviewDbProtoTest.java
+++ b/javatests/com/google/gerrit/proto/ReviewDbProtoTest.java
@@ -18,9 +18,10 @@
 
 import com.google.gerrit.proto.reviewdb.Reviewdb.Change;
 import com.google.gerrit.proto.reviewdb.Reviewdb.Change_Id;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class ReviewDbProtoTest {
+public class ReviewDbProtoTest extends GerritBaseTests {
   @Test
   public void generatedProtoApi() {
     Change c1 = Change.newBuilder().setChangeId(Change_Id.newBuilder().setId(1234).build()).build();
diff --git a/javatests/com/google/gerrit/server/ChangeUtilTest.java b/javatests/com/google/gerrit/server/ChangeUtilTest.java
index 5f73d2c..5cb474d 100644
--- a/javatests/com/google/gerrit/server/ChangeUtilTest.java
+++ b/javatests/com/google/gerrit/server/ChangeUtilTest.java
@@ -16,10 +16,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.regex.Pattern;
 import org.junit.Test;
 
-public class ChangeUtilTest {
+public class ChangeUtilTest extends GerritBaseTests {
   @Test
   public void changeMessageUuid() throws Exception {
     Pattern pat = Pattern.compile("^[0-9a-f]{8}_[0-9a-f]{8}$");
diff --git a/javatests/com/google/gerrit/server/IdentifiedUserTest.java b/javatests/com/google/gerrit/server/IdentifiedUserTest.java
index da6c56d..a8daac3 100644
--- a/javatests/com/google/gerrit/server/IdentifiedUserTest.java
+++ b/javatests/com/google/gerrit/server/IdentifiedUserTest.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.ConfigSuite;
 import com.google.gerrit.testing.FakeAccountCache;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
@@ -44,7 +45,7 @@
 import org.junit.runner.RunWith;
 
 @RunWith(ConfigSuite.class)
-public class IdentifiedUserTest {
+public class IdentifiedUserTest extends GerritBaseTests {
   @ConfigSuite.Parameter public Config config;
 
   private IdentifiedUser identifiedUser;
diff --git a/javatests/com/google/gerrit/server/account/AuthorizedKeysTest.java b/javatests/com/google/gerrit/server/account/AuthorizedKeysTest.java
index 80a15a3..fff8a86 100644
--- a/javatests/com/google/gerrit/server/account/AuthorizedKeysTest.java
+++ b/javatests/com/google/gerrit/server/account/AuthorizedKeysTest.java
@@ -17,12 +17,13 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import org.junit.Test;
 
-public class AuthorizedKeysTest {
+public class AuthorizedKeysTest extends GerritBaseTests {
   private static final String KEY1 =
       "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCgug5VyMXQGnem2H1KVC4/HcRcD4zzBqS"
           + "uJBRWVonSSoz3RoAZ7bWXCVVGwchtXwUURD689wFYdiPecOrWOUgeeyRq754YWRhU+W28"
diff --git a/javatests/com/google/gerrit/server/account/DestinationListTest.java b/javatests/com/google/gerrit/server/account/DestinationListTest.java
index 1f6ed60..e51b041 100644
--- a/javatests/com/google/gerrit/server/account/DestinationListTest.java
+++ b/javatests/com/google/gerrit/server/account/DestinationListTest.java
@@ -15,19 +15,19 @@
 package com.google.gerrit.server.account;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.replay;
 
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.ValidationError;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
-import junit.framework.TestCase;
 import org.junit.Test;
 
-public class DestinationListTest extends TestCase {
+public class DestinationListTest extends GerritBaseTests {
   public static final String R_FOO = "refs/heads/foo";
   public static final String R_BAR = "refs/heads/bar";
 
@@ -128,11 +128,12 @@
     assertThat(branches).contains(B_COMPLEX);
   }
 
-  @Test(expected = IOException.class)
+  @Test
   public void testParseBad() throws IOException {
-    ValidationError.Sink sink = createNiceMock(ValidationError.Sink.class);
-    replay(sink);
-    new DestinationList().parseLabel(LABEL, L_BAD, sink);
+    List<ValidationError> errors = new ArrayList<>();
+    new DestinationList().parseLabel(LABEL, L_BAD, errors::add);
+    assertThat(errors)
+        .containsExactly(new ValidationError("destinationslabel", 1, "missing tab delimiter"));
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/account/GroupUUIDTest.java b/javatests/com/google/gerrit/server/account/GroupUUIDTest.java
index 3b72b08..70887e6 100644
--- a/javatests/com/google/gerrit/server/account/GroupUUIDTest.java
+++ b/javatests/com/google/gerrit/server/account/GroupUUIDTest.java
@@ -17,10 +17,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.junit.Test;
 
-public class GroupUUIDTest {
+public class GroupUUIDTest extends GerritBaseTests {
   @Test
   public void createdUuidsForSameInputShouldBeDifferent() {
     String groupName = "Users";
diff --git a/javatests/com/google/gerrit/server/account/HashedPasswordTest.java b/javatests/com/google/gerrit/server/account/HashedPasswordTest.java
index 4955c06..9a0c9cb9 100644
--- a/javatests/com/google/gerrit/server/account/HashedPasswordTest.java
+++ b/javatests/com/google/gerrit/server/account/HashedPasswordTest.java
@@ -17,10 +17,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.base.Strings;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.apache.commons.codec.DecoderException;
 import org.junit.Test;
 
-public class HashedPasswordTest {
+public class HashedPasswordTest extends GerritBaseTests {
 
   @Test
   public void encodeOneLine() throws Exception {
diff --git a/javatests/com/google/gerrit/server/account/QueryListTest.java b/javatests/com/google/gerrit/server/account/QueryListTest.java
index 2792de8..a0876e1 100644
--- a/javatests/com/google/gerrit/server/account/QueryListTest.java
+++ b/javatests/com/google/gerrit/server/account/QueryListTest.java
@@ -15,15 +15,14 @@
 package com.google.gerrit.server.account;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.replay;
 
 import com.google.gerrit.server.git.ValidationError;
-import java.io.IOException;
-import junit.framework.TestCase;
+import com.google.gerrit.testing.GerritBaseTests;
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Test;
 
-public class QueryListTest extends TestCase {
+public class QueryListTest extends GerritBaseTests {
   public static final String Q_P = "project:foo";
   public static final String Q_B = "branch:bar";
   public static final String Q_COMPLEX = "branch:bar AND peers:'is:open\t'";
@@ -99,11 +98,11 @@
     assertThat(ql.getQuery(N_FOO)).isEqualTo(Q_COMPLEX);
   }
 
-  @Test(expected = IOException.class)
+  @Test
   public void testParseBad() throws Exception {
-    ValidationError.Sink sink = createNiceMock(ValidationError.Sink.class);
-    replay(sink);
-    QueryList.parse(L_BAD, sink);
+    List<ValidationError> errors = new ArrayList<>();
+    assertThat(QueryList.parse(L_BAD, errors::add).asText()).isNull();
+    assertThat(errors).containsExactly(new ValidationError("queries", 1, "missing tab delimiter"));
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
index f29ff1f..edf6bdd 100644
--- a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
+++ b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
@@ -25,12 +25,13 @@
 import com.google.gerrit.server.account.externalids.AllExternalIds.Serializer;
 import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto;
 import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto.ExternalIdProto;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.TypeLiteral;
 import java.util.Arrays;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class AllExternalIdsTest {
+public class AllExternalIdsTest extends GerritBaseTests {
   @Test
   public void serializeEmptyExternalIds() throws Exception {
     assertRoundTrip(allExternalIds(), AllExternalIdsProto.getDefaultInstance());
diff --git a/javatests/com/google/gerrit/server/cache/BUILD b/javatests/com/google/gerrit/server/cache/BUILD
index 4950266..c255e61 100644
--- a/javatests/com/google/gerrit/server/cache/BUILD
+++ b/javatests/com/google/gerrit/server/cache/BUILD
@@ -5,6 +5,7 @@
     srcs = glob(["*.java"]),
     deps = [
         "//java/com/google/gerrit/server",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:junit",
         "//lib/truth",
     ],
diff --git a/javatests/com/google/gerrit/server/cache/PerThreadCacheTest.java b/javatests/com/google/gerrit/server/cache/PerThreadCacheTest.java
index cfb5f3f..6a42577 100644
--- a/javatests/com/google/gerrit/server/cache/PerThreadCacheTest.java
+++ b/javatests/com/google/gerrit/server/cache/PerThreadCacheTest.java
@@ -16,14 +16,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.function.Supplier;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class PerThreadCacheTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
+public class PerThreadCacheTest extends GerritBaseTests {
   @Test
   public void key_respectsClass() {
     assertThat(PerThreadCache.Key.create(String.class))
diff --git a/javatests/com/google/gerrit/server/cache/serialize/BUILD b/javatests/com/google/gerrit/server/cache/serialize/BUILD
index 35d8527..ddad4b9 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/BUILD
+++ b/javatests/com/google/gerrit/server/cache/serialize/BUILD
@@ -6,6 +6,7 @@
     deps = [
         "//java/com/google/gerrit/server/cache/serialize",
         "//java/com/google/gerrit/server/cache/testing",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib:gwtorm",
         "//lib:junit",
diff --git a/javatests/com/google/gerrit/server/cache/serialize/BooleanCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/BooleanCacheSerializerTest.java
index 7504850..c634a78 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/BooleanCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/BooleanCacheSerializerTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assert_;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.protobuf.TextFormat;
 import org.junit.Test;
 
-public class BooleanCacheSerializerTest {
+public class BooleanCacheSerializerTest extends GerritBaseTests {
   @Test
   public void serialize() throws Exception {
     assertThat(BooleanCacheSerializer.INSTANCE.serialize(true))
diff --git a/javatests/com/google/gerrit/server/cache/serialize/EnumCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/EnumCacheSerializerTest.java
index 0b80fc7..c6efc21 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/EnumCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/EnumCacheSerializerTest.java
@@ -18,9 +18,10 @@
 import static com.google.common.truth.Truth.assert_;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class EnumCacheSerializerTest {
+public class EnumCacheSerializerTest extends GerritBaseTests {
   @Test
   public void serialize() throws Exception {
     assertRoundTrip(MyEnum.FOO);
diff --git a/javatests/com/google/gerrit/server/cache/serialize/IntKeyCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/IntKeyCacheSerializerTest.java
index 987a62a..56dd6ad 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/IntKeyCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/IntKeyCacheSerializerTest.java
@@ -17,11 +17,12 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assert_;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gwtorm.client.IntKey;
 import com.google.gwtorm.client.Key;
 import org.junit.Test;
 
-public class IntKeyCacheSerializerTest {
+public class IntKeyCacheSerializerTest extends GerritBaseTests {
 
   private static class MyIntKey extends IntKey<Key<?>> {
     private static final long serialVersionUID = 1L;
diff --git a/javatests/com/google/gerrit/server/cache/serialize/IntegerCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/IntegerCacheSerializerTest.java
index c2db808..1d54010 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/IntegerCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/IntegerCacheSerializerTest.java
@@ -19,10 +19,11 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.primitives.Bytes;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.protobuf.TextFormat;
 import org.junit.Test;
 
-public class IntegerCacheSerializerTest {
+public class IntegerCacheSerializerTest extends GerritBaseTests {
   @Test
   public void serialize() throws Exception {
     for (int i :
diff --git a/javatests/com/google/gerrit/server/cache/serialize/JavaCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/JavaCacheSerializerTest.java
index 6596730..9fcb8a4 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/JavaCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/JavaCacheSerializerTest.java
@@ -17,10 +17,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.auto.value.AutoValue;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.Serializable;
 import org.junit.Test;
 
-public class JavaCacheSerializerTest {
+public class JavaCacheSerializerTest extends GerritBaseTests {
   @Test
   public void builtInTypes() throws Exception {
     assertRoundTrip("foo");
diff --git a/javatests/com/google/gerrit/server/cache/serialize/ObjectIdCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/ObjectIdCacheSerializerTest.java
index c56f8f8..257be54 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/ObjectIdCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/ObjectIdCacheSerializerTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assert_;
 import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteArray;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class ObjectIdCacheSerializerTest {
+public class ObjectIdCacheSerializerTest extends GerritBaseTests {
   @Test
   public void serialize() {
     ObjectId id = ObjectId.fromString("aabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
diff --git a/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java b/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java
index 69694fe..8a02af2 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java
@@ -22,11 +22,12 @@
 import com.google.gerrit.server.cache.proto.Cache.ChangeNotesKeyProto;
 import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto;
 import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.protobuf.ByteString;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class ProtoCacheSerializersTest {
+public class ProtoCacheSerializersTest extends GerritBaseTests {
   @Test
   public void objectIdFromByteString() {
     ObjectIdConverter idConverter = ObjectIdConverter.create();
diff --git a/javatests/com/google/gerrit/server/cache/serialize/StringCacheSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/StringCacheSerializerTest.java
index fa3b7d7..ff0cf9a 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/StringCacheSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/StringCacheSerializerTest.java
@@ -17,11 +17,12 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assert_;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.StandardCharsets;
 import org.junit.Test;
 
-public class StringCacheSerializerTest {
+public class StringCacheSerializerTest extends GerritBaseTests {
   @Test
   public void serialize() {
     assertThat(StringCacheSerializer.INSTANCE.serialize("")).isEmpty();
diff --git a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
index b847ed7..335ff12 100644
--- a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
+++ b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
@@ -23,10 +23,11 @@
 import com.google.gerrit.server.cache.proto.Cache.ChangeKindKeyProto;
 import com.google.gerrit.server.cache.serialize.CacheSerializer;
 import com.google.gerrit.server.change.ChangeKindCacheImpl.Key;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class ChangeKindCacheImplTest {
+public class ChangeKindCacheImplTest extends GerritBaseTests {
   @Test
   public void keySerializer() throws Exception {
     ChangeKindCacheImpl.Key key =
diff --git a/javatests/com/google/gerrit/server/change/HashtagsTest.java b/javatests/com/google/gerrit/server/change/HashtagsTest.java
index 780ac71..49d2952 100644
--- a/javatests/com/google/gerrit/server/change/HashtagsTest.java
+++ b/javatests/com/google/gerrit/server/change/HashtagsTest.java
@@ -17,9 +17,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.Sets;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class HashtagsTest {
+public class HashtagsTest extends GerritBaseTests {
   @Test
   public void emptyCommitMessage() throws Exception {
     assertThat(HashtagsUtil.extractTags("")).isEmpty();
diff --git a/javatests/com/google/gerrit/server/change/IncludedInResolverTest.java b/javatests/com/google/gerrit/server/change/IncludedInResolverTest.java
index dca2dcb..0cfe483 100644
--- a/javatests/com/google/gerrit/server/change/IncludedInResolverTest.java
+++ b/javatests/com/google/gerrit/server/change/IncludedInResolverTest.java
@@ -15,22 +15,19 @@
 package com.google.gerrit.server.change;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_TAGS;
 
-import java.io.IOException;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
-import org.eclipse.jgit.junit.RepositoryTestCase;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
+import com.google.gerrit.testing.GerritBaseTests;
+import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTag;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-public class IncludedInResolverTest extends RepositoryTestCase {
-
+public class IncludedInResolverTest extends GerritBaseTests {
   // Branch names
   private static final String BRANCH_MASTER = "master";
   private static final String BRANCH_1_0 = "rel-1.0";
@@ -53,12 +50,11 @@
   private RevCommit commit_v1_3;
   private RevCommit commit_v2_5;
 
-  private RevWalk revWalk;
+  private TestRepository<?> tr;
 
-  @Override
   @Before
   public void setUp() throws Exception {
-    super.setUp();
+    tr = new TestRepository<>(new InMemoryRepository(new DfsRepositoryDescription("repo")));
 
     /*- The following graph will be created.
 
@@ -78,55 +74,37 @@
 
     */
 
-    // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
-    @SuppressWarnings("resource")
-    Git git = new Git(db);
-    revWalk = new RevWalk(db);
     // Version 1.0
-    commit_initial = git.commit().setMessage("c1").call();
-    git.commit().setMessage("c2").call();
-    RevCommit commit_v1_0 = git.commit().setMessage("version 1.0").call();
-    git.tag().setName(TAG_1_0).setObjectId(commit_v1_0).call();
-    RevCommit c3 = git.commit().setMessage("c3").call();
+    commit_initial = tr.branch(BRANCH_MASTER).commit().message("c1").create();
+    tr.branch(BRANCH_MASTER).commit().message("c2").create();
+    RevCommit commit_v1_0 = tr.branch(BRANCH_MASTER).commit().message("version 1.0").create();
+    tag(TAG_1_0, commit_v1_0);
+    RevCommit c3 = tr.branch(BRANCH_MASTER).commit().message("c3").create();
+
     // Version 1.01
-    createAndCheckoutBranch(commit_v1_0, BRANCH_1_0);
-    RevCommit commit_v1_0_1 = git.commit().setMessage("verREFS_HEADS_RELsion 1.0.1").call();
-    git.tag().setName(TAG_1_0_1).setObjectId(commit_v1_0_1).call();
+    tr.branch(BRANCH_1_0).update(commit_v1_0);
+    RevCommit commit_v1_0_1 = tr.branch(BRANCH_1_0).commit().message("version 1.0.1").create();
+    tag(TAG_1_0_1, commit_v1_0_1);
+
     // Version 1.3
-    createAndCheckoutBranch(c3, BRANCH_1_3);
-    commit_v1_3 = git.commit().setMessage("version 1.3").call();
-    git.tag().setName(TAG_1_3).setObjectId(commit_v1_3).call();
+    tr.branch(BRANCH_1_3).update(c3);
+    commit_v1_3 = tr.branch(BRANCH_1_3).commit().message("version 1.3").create();
+    tag(TAG_1_3, commit_v1_3);
+
     // Version 2.0
-    createAndCheckoutBranch(c3, BRANCH_2_0);
-    RevCommit commit_v2_0 = git.commit().setMessage("version 2.0").call();
-    git.tag().setName(TAG_2_0).setObjectId(commit_v2_0).call();
-    RevCommit commit_v2_0_1 = git.commit().setMessage("version 2.0.1").call();
-    git.tag().setName(TAG_2_0_1).setObjectId(commit_v2_0_1).call();
+    tr.branch(BRANCH_2_0).update(c3);
+    RevCommit commit_v2_0 = tr.branch(BRANCH_2_0).commit().message("version 2.0").create();
+    tag(TAG_2_0, commit_v2_0);
+    RevCommit commit_v2_0_1 = tr.branch(BRANCH_2_0).commit().message("version 2.0.1").create();
+    tag(TAG_2_0_1, commit_v2_0_1);
 
     // Version 2.5
-    createAndCheckoutBranch(commit_v1_3, BRANCH_2_5);
-    git.merge()
-        .include(commit_v2_0_1)
-        .setCommit(false)
-        .setFastForward(FastForwardMode.NO_FF)
-        .call();
-    commit_v2_5 = git.commit().setMessage("version 2.5").call();
-    git.tag().setName(TAG_2_5).setObjectId(commit_v2_5).setAnnotated(false).call();
-    Ref ref_tag_2_5_annotated =
-        git.tag().setName(TAG_2_5_ANNOTATED).setObjectId(commit_v2_5).setAnnotated(true).call();
-    RevTag tag_2_5_annotated = revWalk.parseTag(ref_tag_2_5_annotated.getObjectId());
-    git.tag()
-        .setName(TAG_2_5_ANNOTATED_TWICE)
-        .setObjectId(tag_2_5_annotated)
-        .setAnnotated(true)
-        .call();
-  }
-
-  @Override
-  @After
-  public void tearDown() throws Exception {
-    revWalk.close();
-    super.tearDown();
+    tr.branch(BRANCH_2_5).update(commit_v1_3);
+    tr.branch(BRANCH_2_5).commit().parent(commit_v2_0_1).create(); // Merge v2.0.1
+    commit_v2_5 = tr.branch(BRANCH_2_5).commit().message("version 2.5").create();
+    tr.update(REFS_TAGS + TAG_2_5, commit_v2_5);
+    RevTag tag_2_5_annotated = tag(TAG_2_5_ANNOTATED, commit_v2_5);
+    tag(TAG_2_5_ANNOTATED_TWICE, tag_2_5_annotated);
   }
 
   @Test
@@ -171,12 +149,10 @@
   }
 
   private IncludedInResolver.Result resolve(RevCommit commit) throws Exception {
-    return IncludedInResolver.resolve(db, revWalk, commit);
+    return IncludedInResolver.resolve(tr.getRepository(), tr.getRevWalk(), commit);
   }
 
-  private void createAndCheckoutBranch(ObjectId objectId, String branchName) throws IOException {
-    String fullBranchName = "refs/heads/" + branchName;
-    super.createBranch(objectId, fullBranchName);
-    super.checkoutBranch(fullBranchName);
+  private RevTag tag(String name, RevObject dest) throws Exception {
+    return tr.update(REFS_TAGS + name, tr.tag(name, dest));
   }
 }
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index 842a5b0..fe980f9 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -48,6 +48,7 @@
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryModule;
 import com.google.inject.Guice;
@@ -62,7 +63,7 @@
 import org.junit.Test;
 
 /** Unit tests for {@link LabelNormalizer}. */
-public class LabelNormalizerTest {
+public class LabelNormalizerTest extends GerritBaseTests {
   @Inject private AccountManager accountManager;
   @Inject private AllProjectsName allProjects;
   @Inject private GitRepositoryManager repoManager;
diff --git a/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java b/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
index e10a236..c5d35f6 100644
--- a/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
+++ b/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
@@ -22,10 +22,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.server.cache.proto.Cache.MergeabilityKeyProto;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class MergeabilityCacheImplTest {
+public class MergeabilityCacheImplTest extends GerritBaseTests {
   @Test
   public void keySerializer() throws Exception {
     MergeabilityCacheImpl.EntryKey key =
diff --git a/javatests/com/google/gerrit/server/config/ConfigUtilTest.java b/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
index 231b584..75fb94e 100644
--- a/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
+++ b/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
@@ -22,13 +22,14 @@
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import com.google.gerrit.extensions.client.Theme;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
-public class ConfigUtilTest {
+public class ConfigUtilTest extends GerritBaseTests {
   private static final String SECT = "foo";
   private static final String SUB = "bar";
 
diff --git a/javatests/com/google/gerrit/server/config/GitwebConfigTest.java b/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
index cb6de34..bf7e4fd 100644
--- a/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
+++ b/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class GitwebConfigTest {
+public class GitwebConfigTest extends GerritBaseTests {
   private static final String VALID_CHARACTERS = "*()";
   private static final String SOME_INVALID_CHARACTERS = "09AZaz$-_.+!',";
 
diff --git a/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java b/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
index fd9c925..a4a196b 100644
--- a/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
+++ b/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.restapi.config.ListCapabilities;
 import com.google.gerrit.server.restapi.config.ListCapabilities.CapabilityInfo;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -33,7 +34,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class ListCapabilitiesTest {
+public class ListCapabilitiesTest extends GerritBaseTests {
   private Injector injector;
 
   @Before
diff --git a/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java b/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
index 3da35b2..2a473f4 100644
--- a/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
+++ b/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
@@ -27,7 +28,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class RepositoryConfigTest {
+public class RepositoryConfigTest extends GerritBaseTests {
 
   private Config cfg;
   private RepositoryConfig repoCfg;
diff --git a/javatests/com/google/gerrit/server/config/ScheduleConfigTest.java b/javatests/com/google/gerrit/server/config/ScheduleConfigTest.java
index 70893a9..f0e9153 100644
--- a/javatests/com/google/gerrit/server/config/ScheduleConfigTest.java
+++ b/javatests/com/google/gerrit/server/config/ScheduleConfigTest.java
@@ -22,6 +22,7 @@
 import static java.util.concurrent.TimeUnit.MINUTES;
 
 import com.google.gerrit.server.config.ScheduleConfig.Schedule;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.time.LocalDateTime;
 import java.time.Month;
 import java.time.ZoneOffset;
@@ -31,7 +32,7 @@
 import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
-public class ScheduleConfigTest {
+public class ScheduleConfigTest extends GerritBaseTests {
 
   // Friday June 13, 2014 10:00 UTC
   private static final ZonedDateTime NOW =
diff --git a/javatests/com/google/gerrit/server/edit/ChangeEditTest.java b/javatests/com/google/gerrit/server/edit/ChangeEditTest.java
index 6509c4b..4c0b5a1 100644
--- a/javatests/com/google/gerrit/server/edit/ChangeEditTest.java
+++ b/javatests/com/google/gerrit/server/edit/ChangeEditTest.java
@@ -20,9 +20,10 @@
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class ChangeEditTest {
+public class ChangeEditTest extends GerritBaseTests {
   @Test
   public void changeEditRef() throws Exception {
     Account.Id accountId = new Account.Id(1000042);
diff --git a/javatests/com/google/gerrit/server/events/EventDeserializerTest.java b/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
index 997fda9..0e63715 100644
--- a/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
+++ b/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
@@ -20,11 +20,12 @@
 import com.google.common.base.Suppliers;
 import com.google.gerrit.server.data.AccountAttribute;
 import com.google.gerrit.server.data.RefUpdateAttribute;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import org.junit.Test;
 
-public class EventDeserializerTest {
+public class EventDeserializerTest extends GerritBaseTests {
 
   @Test
   public void refUpdatedEvent() {
diff --git a/javatests/com/google/gerrit/server/events/EventTypesTest.java b/javatests/com/google/gerrit/server/events/EventTypesTest.java
index c822d6c..dd5c7f9 100644
--- a/javatests/com/google/gerrit/server/events/EventTypesTest.java
+++ b/javatests/com/google/gerrit/server/events/EventTypesTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class EventTypesTest {
+public class EventTypesTest extends GerritBaseTests {
   public static class TestEvent extends Event {
     private static final String TYPE = "test-event";
 
diff --git a/javatests/com/google/gerrit/server/extensions/webui/UiActionsTest.java b/javatests/com/google/gerrit/server/extensions/webui/UiActionsTest.java
index 08d7082..6c5c5b0 100644
--- a/javatests/com/google/gerrit/server/extensions/webui/UiActionsTest.java
+++ b/javatests/com/google/gerrit/server/extensions/webui/UiActionsTest.java
@@ -30,6 +30,7 @@
 import com.google.gerrit.server.permissions.PermissionBackendCondition;
 import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.permissions.ProjectPermission;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
@@ -38,7 +39,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.junit.Test;
 
-public class UiActionsTest {
+public class UiActionsTest extends GerritBaseTests {
 
   private static class FakeForProject extends ForProject {
     private boolean allowValueQueries = true;
diff --git a/javatests/com/google/gerrit/server/fixes/FixReplacementInterpreterTest.java b/javatests/com/google/gerrit/server/fixes/FixReplacementInterpreterTest.java
index c1a65bb..cc648bf 100644
--- a/javatests/com/google/gerrit/server/fixes/FixReplacementInterpreterTest.java
+++ b/javatests/com/google/gerrit/server/fixes/FixReplacementInterpreterTest.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.server.change.FileContentUtil;
 import com.google.gerrit.server.edit.tree.TreeModification;
 import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -33,14 +34,9 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class FixReplacementInterpreterTest {
-
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
+public class FixReplacementInterpreterTest extends GerritBaseTests {
   private final FileContentUtil fileContentUtil = createMock(FileContentUtil.class);
   private final Repository repository = createMock(Repository.class);
   private final ProjectState projectState = createMock(ProjectState.class);
@@ -261,7 +257,7 @@
 
     replay(fileContentUtil);
 
-    expectedException.expect(ResourceConflictException.class);
+    exception.expect(ResourceConflictException.class);
     toTreeModifications(fixReplacement);
   }
 
@@ -273,7 +269,7 @@
 
     replay(fileContentUtil);
 
-    expectedException.expect(ResourceConflictException.class);
+    exception.expect(ResourceConflictException.class);
     toTreeModifications(fixReplacement);
   }
 
@@ -285,7 +281,7 @@
 
     replay(fileContentUtil);
 
-    expectedException.expect(ResourceConflictException.class);
+    exception.expect(ResourceConflictException.class);
     toTreeModifications(fixReplacement);
   }
 
@@ -297,7 +293,7 @@
 
     replay(fileContentUtil);
 
-    expectedException.expect(ResourceConflictException.class);
+    exception.expect(ResourceConflictException.class);
     toTreeModifications(fixReplacement);
   }
 
@@ -309,7 +305,7 @@
 
     replay(fileContentUtil);
 
-    expectedException.expect(ResourceConflictException.class);
+    exception.expect(ResourceConflictException.class);
     toTreeModifications(fixReplacement);
   }
 
diff --git a/javatests/com/google/gerrit/server/fixes/LineIdentifierTest.java b/javatests/com/google/gerrit/server/fixes/LineIdentifierTest.java
index f638346..309f726 100644
--- a/javatests/com/google/gerrit/server/fixes/LineIdentifierTest.java
+++ b/javatests/com/google/gerrit/server/fixes/LineIdentifierTest.java
@@ -16,27 +16,23 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import org.junit.Rule;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class LineIdentifierTest {
-
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
+public class LineIdentifierTest extends GerritBaseTests {
   @Test
   public void lineNumberMustBePositive() {
     LineIdentifier lineIdentifier = new LineIdentifier("First line\nSecond line");
-    expectedException.expect(StringIndexOutOfBoundsException.class);
-    expectedException.expectMessage("positive");
+    exception.expect(StringIndexOutOfBoundsException.class);
+    exception.expectMessage("positive");
     lineIdentifier.getStartIndexOfLine(0);
   }
 
   @Test
   public void lineNumberMustIndicateAnAvailableLine() {
     LineIdentifier lineIdentifier = new LineIdentifier("First line\nSecond line");
-    expectedException.expect(StringIndexOutOfBoundsException.class);
-    expectedException.expectMessage("Line 3 isn't available");
+    exception.expect(StringIndexOutOfBoundsException.class);
+    exception.expectMessage("Line 3 isn't available");
     lineIdentifier.getStartIndexOfLine(3);
   }
 
diff --git a/javatests/com/google/gerrit/server/fixes/StringModifierTest.java b/javatests/com/google/gerrit/server/fixes/StringModifierTest.java
index d23e928..185b58c 100644
--- a/javatests/com/google/gerrit/server/fixes/StringModifierTest.java
+++ b/javatests/com/google/gerrit/server/fixes/StringModifierTest.java
@@ -16,15 +16,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class StringModifierTest {
-
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
+public class StringModifierTest extends GerritBaseTests {
   private final String originalString = "This is the original, unmodified string.";
   private StringModifier stringModifier;
 
@@ -67,19 +63,19 @@
   @Test
   public void replacedPartsMustNotOverlap() {
     stringModifier.replace(0, 9, "");
-    expectedException.expect(StringIndexOutOfBoundsException.class);
+    exception.expect(StringIndexOutOfBoundsException.class);
     stringModifier.replace(8, 32, "The modified");
   }
 
   @Test
   public void startIndexMustNotBeGreaterThanEndIndex() {
-    expectedException.expect(StringIndexOutOfBoundsException.class);
+    exception.expect(StringIndexOutOfBoundsException.class);
     stringModifier.replace(10, 9, "something");
   }
 
   @Test
   public void startIndexMustNotBeNegative() {
-    expectedException.expect(StringIndexOutOfBoundsException.class);
+    exception.expect(StringIndexOutOfBoundsException.class);
     stringModifier.replace(-1, 9, "something");
   }
 
@@ -94,13 +90,13 @@
 
   @Test
   public void startIndexMustNotBeGreaterThanLengthOfString() {
-    expectedException.expect(StringIndexOutOfBoundsException.class);
+    exception.expect(StringIndexOutOfBoundsException.class);
     stringModifier.replace(originalString.length() + 1, originalString.length() + 1, "something");
   }
 
   @Test
   public void endIndexMustNotBeGreaterThanLengthOfString() {
-    expectedException.expect(StringIndexOutOfBoundsException.class);
+    exception.expect(StringIndexOutOfBoundsException.class);
     stringModifier.replace(8, originalString.length() + 1, "something");
   }
 }
diff --git a/javatests/com/google/gerrit/server/git/GroupCollectorTest.java b/javatests/com/google/gerrit/server/git/GroupCollectorTest.java
index e5e8e26..f694299 100644
--- a/javatests/com/google/gerrit/server/git/GroupCollectorTest.java
+++ b/javatests/com/google/gerrit/server/git/GroupCollectorTest.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.SortedSetMultimap;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
@@ -31,7 +32,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class GroupCollectorTest {
+public class GroupCollectorTest extends GerritBaseTests {
   private TestRepository<?> tr;
 
   @Before
diff --git a/javatests/com/google/gerrit/server/git/LocalDiskRepositoryManagerTest.java b/javatests/com/google/gerrit/server/git/LocalDiskRepositoryManagerTest.java
index 4e0cb0c..821a6e6b 100644
--- a/javatests/com/google/gerrit/server/git/LocalDiskRepositoryManagerTest.java
+++ b/javatests/com/google/gerrit/server/git/LocalDiskRepositoryManagerTest.java
@@ -20,13 +20,10 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.ioutil.HostPlatform;
-import com.google.gerrit.testing.TempFileUtil;
-import com.google.gwtorm.client.KeyUtil;
-import com.google.gwtorm.server.StandardKeyEncoder;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import org.easymock.EasyMockSupport;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Constants;
@@ -35,13 +32,12 @@
 import org.eclipse.jgit.lib.RepositoryCache.FileKey;
 import org.eclipse.jgit.util.FS;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
-public class LocalDiskRepositoryManagerTest extends EasyMockSupport {
-
-  static {
-    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
-  }
+public class LocalDiskRepositoryManagerTest extends GerritBaseTests {
+  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
   private Config cfg;
   private SitePaths site;
@@ -49,7 +45,7 @@
 
   @Before
   public void setUp() throws Exception {
-    site = new SitePaths(TempFileUtil.createTempDirectory().toPath());
+    site = new SitePaths(temporaryFolder.newFolder().toPath());
     site.resolve("git").toFile().mkdir();
     cfg = new Config();
     cfg.setString("gerrit", null, "basePath", "git");
diff --git a/javatests/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManagerTest.java b/javatests/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManagerTest.java
index e848fa3..fc79a6d 100644
--- a/javatests/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManagerTest.java
+++ b/javatests/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManagerTest.java
@@ -25,7 +25,6 @@
 import com.google.gerrit.server.config.RepositoryConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.TempFileUtil;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -37,11 +36,14 @@
 import org.eclipse.jgit.lib.RepositoryCache;
 import org.eclipse.jgit.lib.RepositoryCache.FileKey;
 import org.eclipse.jgit.util.FS;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 public class MultiBaseLocalDiskRepositoryManagerTest extends GerritBaseTests {
+  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   private Config cfg;
   private SitePaths site;
   private MultiBaseLocalDiskRepositoryManager repoManager;
@@ -49,7 +51,7 @@
 
   @Before
   public void setUp() throws IOException {
-    site = new SitePaths(TempFileUtil.createTempDirectory().toPath());
+    site = new SitePaths(temporaryFolder.newFolder().toPath());
     site.resolve("git").toFile().mkdir();
     cfg = new Config();
     cfg.setString("gerrit", null, "basePath", "git");
@@ -59,11 +61,6 @@
     repoManager = new MultiBaseLocalDiskRepositoryManager(site, cfg, configMock);
   }
 
-  @After
-  public void tearDown() throws IOException {
-    TempFileUtil.cleanup();
-  }
-
   @Test
   public void defaultRepositoryLocation()
       throws RepositoryCaseMismatchException, RepositoryNotFoundException, IOException {
@@ -91,7 +88,7 @@
 
   @Test
   public void alternateRepositoryLocation() throws IOException {
-    Path alternateBasePath = TempFileUtil.createTempDirectory().toPath();
+    Path alternateBasePath = temporaryFolder.newFolder().toPath();
     Project.NameKey someProjectKey = new Project.NameKey("someProject");
     reset(configMock);
     expect(configMock.getBasePath(someProjectKey)).andReturn(alternateBasePath).anyTimes();
@@ -124,7 +121,7 @@
     Project.NameKey misplacedProject1 = new Project.NameKey("misplacedProject1");
     Project.NameKey misplacedProject2 = new Project.NameKey("misplacedProject2");
 
-    Path alternateBasePath = TempFileUtil.createTempDirectory().toPath();
+    Path alternateBasePath = temporaryFolder.newFolder().toPath();
 
     reset(configMock);
     expect(configMock.getBasePath(altPathProject)).andReturn(alternateBasePath).anyTimes();
diff --git a/javatests/com/google/gerrit/server/git/TagSetHolderTest.java b/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
index 3d3e734..705139a 100644
--- a/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
+++ b/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
@@ -21,9 +21,10 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class TagSetHolderTest {
+public class TagSetHolderTest extends GerritBaseTests {
   @Test
   public void serializerWithTagSet() throws Exception {
     TagSetHolder holder = new TagSetHolder(new Project.NameKey("project"));
diff --git a/javatests/com/google/gerrit/server/git/TagSetTest.java b/javatests/com/google/gerrit/server/git/TagSetTest.java
index 1eebe75..1314ce6 100644
--- a/javatests/com/google/gerrit/server/git/TagSetTest.java
+++ b/javatests/com/google/gerrit/server/git/TagSetTest.java
@@ -30,6 +30,7 @@
 import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto.TagSetProto.TagProto;
 import com.google.gerrit.server.git.TagSet.CachedRef;
 import com.google.gerrit.server.git.TagSet.Tag;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.TypeLiteral;
 import java.lang.reflect.Type;
 import java.util.Arrays;
@@ -42,7 +43,7 @@
 import org.eclipse.jgit.lib.ObjectIdOwnerMap;
 import org.junit.Test;
 
-public class TagSetTest {
+public class TagSetTest extends GerritBaseTests {
   @Test
   public void roundTripToProto() {
     HashMap<String, CachedRef> refs = new HashMap<>();
diff --git a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
index 7ed6c50..dedccc2 100644
--- a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
+++ b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.meta.VersionedMetaData.BatchMetaDataUpdate;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.TestTimeUtil;
 import java.io.IOException;
 import java.util.Arrays;
@@ -50,7 +51,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class VersionedMetaDataTest {
+public class VersionedMetaDataTest extends GerritBaseTests {
   // If you're considering fleshing out this test and making it more comprehensive, please consider
   // instead coming up with a replacement interface for
   // VersionedMetaData/BatchMetaDataUpdate/MetaDataUpdate that is easier to use correctly.
diff --git a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
index a5744d1..6f43380 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
@@ -32,9 +32,8 @@
 import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.group.testing.InternalGroupSubject;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.truth.OptionalSubject;
-import com.google.gwtorm.client.KeyUtil;
-import com.google.gwtorm.server.StandardKeyEncoder;
 import java.io.IOException;
 import java.sql.Timestamp;
 import java.time.LocalDate;
@@ -53,18 +52,9 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class GroupConfigTest {
-  static {
-    // Necessary so that toString() methods of ReviewDb entities work correctly.
-    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
-  }
-
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
+public class GroupConfigTest extends GerritBaseTests {
   private Project.NameKey projectName;
   private Repository repository;
   private TestRepository<?> testRepository;
@@ -122,8 +112,8 @@
     GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Name of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Name of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -135,8 +125,8 @@
     GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Name of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Name of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -157,8 +147,8 @@
     GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("ID of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("ID of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -236,8 +226,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Owner UUID of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Owner UUID of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -251,8 +241,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Owner UUID of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Owner UUID of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -362,8 +352,8 @@
   public void idInConfigMustBeDefined() throws Exception {
     populateGroupConfig(groupUuid, "[group]\n\tname = users\n\townerGroupUuid = owners\n");
 
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage("ID of the group " + groupUuid);
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage("ID of the group " + groupUuid);
     GroupConfig.loadForGroup(projectName, repository, groupUuid);
   }
 
@@ -372,8 +362,8 @@
     populateGroupConfig(
         groupUuid, "[group]\n\tname = users\n\tid = -5\n\townerGroupUuid = owners\n");
 
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage("ID of the group " + groupUuid);
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage("ID of the group " + groupUuid);
     GroupConfig.loadForGroup(projectName, repository, groupUuid);
   }
 
@@ -398,8 +388,8 @@
   public void ownerGroupUuidInConfigMustBeDefined() throws Exception {
     populateGroupConfig(groupUuid, "[group]\n\tname = users\n\tid = 42\n");
 
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage("Owner UUID of the group " + groupUuid);
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage("Owner UUID of the group " + groupUuid);
     GroupConfig.loadForGroup(projectName, repository, groupUuid);
   }
 
@@ -452,8 +442,8 @@
     populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
     populateMembersFile(groupUuid, "One");
 
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage("Invalid file members");
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage("Invalid file members");
     loadGroup(groupUuid);
   }
 
@@ -462,8 +452,8 @@
     populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
     populateMembersFile(groupUuid, "1\t2");
 
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage("Invalid file members");
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage("Invalid file members");
     loadGroup(groupUuid);
   }
 
@@ -554,8 +544,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Name of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Name of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -570,8 +560,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Name of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Name of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -637,8 +627,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Owner UUID of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Owner UUID of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
@@ -653,8 +643,8 @@
     groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
 
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
-      expectedException.expectCause(instanceOf(ConfigInvalidException.class));
-      expectedException.expectMessage("Owner UUID of the group " + groupUuid);
+      exception.expectCause(instanceOf(ConfigInvalidException.class));
+      exception.expectMessage("Owner UUID of the group " + groupUuid);
       groupConfig.commit(metaDataUpdate);
     }
   }
diff --git a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
index 7364c95..cff8189 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
@@ -36,13 +36,12 @@
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.GitTestUtil;
 import com.google.gerrit.testing.TestTimeUtil;
 import com.google.gerrit.truth.ListSubject;
 import com.google.gerrit.truth.OptionalSubject;
-import com.google.gwtorm.client.KeyUtil;
 import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.StandardKeyEncoder;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
@@ -66,21 +65,13 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class GroupNameNotesTest {
-  static {
-    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
-  }
-
+public class GroupNameNotesTest extends GerritBaseTests {
   private static final String SERVER_NAME = "Gerrit Server";
   private static final String SERVER_EMAIL = "noreply@gerritcodereview.com";
   private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
 
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
   private final AccountGroup.UUID groupUuid = new AccountGroup.UUID("users-XYZ");
   private final AccountGroup.NameKey groupName = new AccountGroup.NameKey("users");
 
@@ -112,13 +103,13 @@
 
   @Test
   public void uuidOfNewGroupMustNotBeNull() throws Exception {
-    expectedException.expect(NullPointerException.class);
+    exception.expect(NullPointerException.class);
     GroupNameNotes.forNewGroup(allUsersName, repo, null, groupName);
   }
 
   @Test
   public void nameOfNewGroupMustNotBeNull() throws Exception {
-    expectedException.expect(NullPointerException.class);
+    exception.expect(NullPointerException.class);
     GroupNameNotes.forNewGroup(allUsersName, repo, groupUuid, null);
   }
 
@@ -136,8 +127,8 @@
     createGroup(groupUuid, groupName);
 
     AccountGroup.UUID anotherGroupUuid = new AccountGroup.UUID("AnotherGroup");
-    expectedException.expect(OrmDuplicateKeyException.class);
-    expectedException.expectMessage(groupName.get());
+    exception.expect(OrmDuplicateKeyException.class);
+    exception.expectMessage(groupName.get());
     GroupNameNotes.forNewGroup(allUsersName, repo, anotherGroupUuid, groupName);
   }
 
@@ -181,7 +172,7 @@
   public void groupCannotBeRenamedToNull() throws Exception {
     createGroup(groupUuid, groupName);
 
-    expectedException.expect(NullPointerException.class);
+    exception.expect(NullPointerException.class);
     GroupNameNotes.forRename(allUsersName, repo, groupUuid, groupName, null);
   }
 
@@ -190,7 +181,7 @@
     createGroup(groupUuid, groupName);
 
     AccountGroup.NameKey anotherName = new AccountGroup.NameKey("admins");
-    expectedException.expect(NullPointerException.class);
+    exception.expect(NullPointerException.class);
     GroupNameNotes.forRename(allUsersName, repo, groupUuid, null, anotherName);
   }
 
@@ -200,8 +191,8 @@
 
     AccountGroup.NameKey anotherOldName = new AccountGroup.NameKey("contributors");
     AccountGroup.NameKey anotherName = new AccountGroup.NameKey("admins");
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage(anotherOldName.get());
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage(anotherOldName.get());
     GroupNameNotes.forRename(allUsersName, repo, groupUuid, anotherOldName, anotherName);
   }
 
@@ -212,8 +203,8 @@
     AccountGroup.NameKey anotherGroupName = new AccountGroup.NameKey("admins");
     createGroup(anotherGroupUuid, anotherGroupName);
 
-    expectedException.expect(OrmDuplicateKeyException.class);
-    expectedException.expectMessage(anotherGroupName.get());
+    exception.expect(OrmDuplicateKeyException.class);
+    exception.expectMessage(anotherGroupName.get());
     GroupNameNotes.forRename(allUsersName, repo, groupUuid, groupName, anotherGroupName);
   }
 
@@ -222,7 +213,7 @@
     createGroup(groupUuid, groupName);
 
     AccountGroup.NameKey anotherName = new AccountGroup.NameKey("admins");
-    expectedException.expect(NullPointerException.class);
+    exception.expect(NullPointerException.class);
     GroupNameNotes.forRename(allUsersName, repo, null, groupName, anotherName);
   }
 
@@ -232,8 +223,8 @@
 
     AccountGroup.UUID anotherGroupUuid = new AccountGroup.UUID("admins-ABC");
     AccountGroup.NameKey anotherName = new AccountGroup.NameKey("admins");
-    expectedException.expect(ConfigInvalidException.class);
-    expectedException.expectMessage(groupUuid.get());
+    exception.expect(ConfigInvalidException.class);
+    exception.expectMessage(groupUuid.get());
     GroupNameNotes.forRename(allUsersName, repo, anotherGroupUuid, groupName, anotherName);
   }
 
diff --git a/javatests/com/google/gerrit/server/ioutil/BUILD b/javatests/com/google/gerrit/server/ioutil/BUILD
index ac9530f..ef02243 100644
--- a/javatests/com/google/gerrit/server/ioutil/BUILD
+++ b/javatests/com/google/gerrit/server/ioutil/BUILD
@@ -10,6 +10,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//java/com/google/gerrit/server/ioutil",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/truth",
         "//lib/truth:truth-java8-extension",
diff --git a/javatests/com/google/gerrit/server/ioutil/BasicSerializationTest.java b/javatests/com/google/gerrit/server/ioutil/BasicSerializationTest.java
index fae8559..c4f32c7 100644
--- a/javatests/com/google/gerrit/server/ioutil/BasicSerializationTest.java
+++ b/javatests/com/google/gerrit/server/ioutil/BasicSerializationTest.java
@@ -23,13 +23,14 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import org.junit.Test;
 
-public class BasicSerializationTest {
+public class BasicSerializationTest extends GerritBaseTests {
   @Test
   public void testReadVarInt32() throws IOException {
     assertEquals(0x00000000, readVarInt32(r(b(0))));
diff --git a/javatests/com/google/gerrit/server/ioutil/ColumnFormatterTest.java b/javatests/com/google/gerrit/server/ioutil/ColumnFormatterTest.java
index fe642ba..9f5e60a 100644
--- a/javatests/com/google/gerrit/server/ioutil/ColumnFormatterTest.java
+++ b/javatests/com/google/gerrit/server/ioutil/ColumnFormatterTest.java
@@ -14,12 +14,13 @@
 
 package com.google.gerrit.server.ioutil;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class ColumnFormatterTest {
+public class ColumnFormatterTest extends GerritBaseTests {
   /**
    * Holds an in-memory {@link java.io.PrintWriter} object and allows comparisons of its contents to
    * a supplied string via an assert statement.
diff --git a/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java b/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java
index 9bb6951..40fd71f 100644
--- a/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java
+++ b/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java
@@ -16,9 +16,10 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class HexFormatTest {
+public class HexFormatTest extends GerritBaseTests {
 
   @Test
   public void fromInt() {
diff --git a/javatests/com/google/gerrit/server/ioutil/RegexListSearcherTest.java b/javatests/com/google/gerrit/server/ioutil/RegexListSearcherTest.java
index 3043985..33b1c4f 100644
--- a/javatests/com/google/gerrit/server/ioutil/RegexListSearcherTest.java
+++ b/javatests/com/google/gerrit/server/ioutil/RegexListSearcherTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth8.assertThat;
 
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.List;
 import org.junit.Test;
 
-public class RegexListSearcherTest {
+public class RegexListSearcherTest extends GerritBaseTests {
   private static final ImmutableList<String> EMPTY = ImmutableList.of();
 
   @Test
diff --git a/javatests/com/google/gerrit/server/ioutil/StringUtilTest.java b/javatests/com/google/gerrit/server/ioutil/StringUtilTest.java
index 04f806d..817b317 100644
--- a/javatests/com/google/gerrit/server/ioutil/StringUtilTest.java
+++ b/javatests/com/google/gerrit/server/ioutil/StringUtilTest.java
@@ -16,9 +16,10 @@
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class StringUtilTest {
+public class StringUtilTest extends GerritBaseTests {
   /** Test the boundary condition that the first character of a string should be escaped. */
   @Test
   public void escapeFirstChar() {
diff --git a/javatests/com/google/gerrit/server/logging/LoggingContextAwareExecutorServiceTest.java b/javatests/com/google/gerrit/server/logging/LoggingContextAwareExecutorServiceTest.java
index 5117c01..463decf 100644
--- a/javatests/com/google/gerrit/server/logging/LoggingContextAwareExecutorServiceTest.java
+++ b/javatests/com/google/gerrit/server/logging/LoggingContextAwareExecutorServiceTest.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.truth.Expect;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.SortedMap;
 import java.util.SortedSet;
 import java.util.concurrent.ExecutorService;
@@ -24,7 +25,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-public class LoggingContextAwareExecutorServiceTest {
+public class LoggingContextAwareExecutorServiceTest extends GerritBaseTests {
   @Rule public final Expect expect = Expect.create();
 
   @Test
diff --git a/javatests/com/google/gerrit/server/logging/MutableTagsTest.java b/javatests/com/google/gerrit/server/logging/MutableTagsTest.java
index 4fadbb4..113f26c 100644
--- a/javatests/com/google/gerrit/server/logging/MutableTagsTest.java
+++ b/javatests/com/google/gerrit/server/logging/MutableTagsTest.java
@@ -20,13 +20,14 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.SortedSet;
 import org.junit.Before;
 import org.junit.Test;
 
-public class MutableTagsTest {
+public class MutableTagsTest extends GerritBaseTests {
   private MutableTags tags;
 
   @Before
diff --git a/javatests/com/google/gerrit/server/logging/TraceContextTest.java b/javatests/com/google/gerrit/server/logging/TraceContextTest.java
index 044d237..19b2eeb 100644
--- a/javatests/com/google/gerrit/server/logging/TraceContextTest.java
+++ b/javatests/com/google/gerrit/server/logging/TraceContextTest.java
@@ -19,13 +19,14 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.server.logging.TraceContext.TraceIdConsumer;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.SortedSet;
 import org.junit.After;
 import org.junit.Test;
 
-public class TraceContextTest {
+public class TraceContextTest extends GerritBaseTests {
   @After
   public void cleanup() {
     LoggingContext.getInstance().clearTags();
diff --git a/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java b/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java
index f4fbc78..78116ed 100644
--- a/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java
@@ -20,10 +20,11 @@
 import static com.google.gerrit.server.mail.send.CommentFormatter.BlockType.PRE_FORMATTED;
 import static com.google.gerrit.server.mail.send.CommentFormatter.BlockType.QUOTE;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.List;
 import org.junit.Test;
 
-public class CommentFormatterTest {
+public class CommentFormatterTest extends GerritBaseTests {
   private void assertBlock(
       List<CommentFormatter.Block> list, int index, CommentFormatter.BlockType type, String text) {
     CommentFormatter.Block block = list.get(index);
diff --git a/javatests/com/google/gerrit/server/mail/send/CommentSenderTest.java b/javatests/com/google/gerrit/server/mail/send/CommentSenderTest.java
index 6b6632c..87e98fd 100644
--- a/javatests/com/google/gerrit/server/mail/send/CommentSenderTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/CommentSenderTest.java
@@ -16,11 +16,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gwtorm.server.OrmException;
 import java.util.Collections;
 import org.junit.Test;
 
-public class CommentSenderTest {
+public class CommentSenderTest extends GerritBaseTests {
   private static class TestSender extends CommentSender {
     TestSender() throws OrmException {
       super(null, null, null, null, null);
diff --git a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
index 75923b4..537ebff 100644
--- a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
@@ -28,6 +28,7 @@
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.AllUsersNameProvider;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
@@ -36,7 +37,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class FromAddressGeneratorProviderTest {
+public class FromAddressGeneratorProviderTest extends GerritBaseTests {
   private Config config;
   private PersonIdent ident;
   private AccountCache accountCache;
diff --git a/javatests/com/google/gerrit/server/mail/send/NotificationEmailTest.java b/javatests/com/google/gerrit/server/mail/send/NotificationEmailTest.java
index 885f7cd..5d6fce7 100644
--- a/javatests/com/google/gerrit/server/mail/send/NotificationEmailTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/NotificationEmailTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class NotificationEmailTest {
+public class NotificationEmailTest extends GerritBaseTests {
 
   @Test
   public void getInstanceAndProjectName_returnsTheRightValue() {
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 7b41ba3..1bd6fbe 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -50,8 +50,7 @@
 import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
 import com.google.gerrit.server.notedb.ChangeNotesState.ChangeColumns;
 import com.google.gerrit.server.notedb.ChangeNotesState.Serializer;
-import com.google.gwtorm.client.KeyUtil;
-import com.google.gwtorm.server.StandardKeyEncoder;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.inject.TypeLiteral;
 import com.google.protobuf.ByteString;
 import java.lang.reflect.Type;
@@ -62,11 +61,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class ChangeNotesStateTest {
-  static {
-    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
-  }
-
+public class ChangeNotesStateTest extends GerritBaseTests {
   private static final Change.Id ID = new Change.Id(123);
   private static final ObjectId SHA =
       ObjectId.fromString("1234567812345678123456781234567812345678");
diff --git a/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java b/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
index e7d8956..4dd2005 100644
--- a/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
@@ -18,6 +18,7 @@
 
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Comment;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import java.sql.Timestamp;
@@ -28,7 +29,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class CommentTimestampAdapterTest {
+public class CommentTimestampAdapterTest extends GerritBaseTests {
   /** Arbitrary time outside of a DST transition, as an ISO instant. */
   private static final String NON_DST_STR = "2017-02-07T10:20:30.123Z";
 
diff --git a/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java b/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
index 64fd875..5aad6ff 100644
--- a/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
+++ b/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import com.google.gwtorm.server.OrmException;
 import java.io.IOException;
@@ -40,17 +41,13 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
-public class RepoSequenceTest {
+public class RepoSequenceTest extends GerritBaseTests {
   // Don't sleep in tests.
   private static final Retryer<RefUpdate> RETRYER =
       RepoSequence.retryerBuilder().withBlockStrategy(t -> {}).build();
 
-  @Rule public ExpectedException exception = ExpectedException.none();
-
   private InMemoryRepositoryManager repoManager;
   private Project.NameKey project;
 
diff --git a/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java b/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java
index c81a176..7fb9d82 100644
--- a/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java
+++ b/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.notedb.ChangeUpdate;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.TestTimeUtil;
 import java.sql.Timestamp;
 import java.util.ArrayList;
@@ -34,7 +35,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class EventSorterTest {
+public class EventSorterTest extends GerritBaseTests {
   private class TestEvent extends Event {
     protected TestEvent(Timestamp when) {
       super(
diff --git a/javatests/com/google/gerrit/server/patch/IntraLineLoaderTest.java b/javatests/com/google/gerrit/server/patch/IntraLineLoaderTest.java
index ef80d7e..0cc4b00 100644
--- a/javatests/com/google/gerrit/server/patch/IntraLineLoaderTest.java
+++ b/javatests/com/google/gerrit/server/patch/IntraLineLoaderTest.java
@@ -19,13 +19,14 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.List;
 import org.eclipse.jgit.diff.Edit;
 import org.eclipse.jgit.diff.EditList;
 import org.eclipse.jgit.diff.ReplaceEdit;
 import org.junit.Test;
 
-public class IntraLineLoaderTest {
+public class IntraLineLoaderTest extends GerritBaseTests {
 
   @Test
   public void rewriteAtStartOfLineIsRecognized() throws Exception {
diff --git a/javatests/com/google/gerrit/server/patch/PatchListEntryTest.java b/javatests/com/google/gerrit/server/patch/PatchListEntryTest.java
index 81f03af..4ed5f4b 100644
--- a/javatests/com/google/gerrit/server/patch/PatchListEntryTest.java
+++ b/javatests/com/google/gerrit/server/patch/PatchListEntryTest.java
@@ -20,9 +20,10 @@
 import static org.junit.Assert.assertTrue;
 
 import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class PatchListEntryTest {
+public class PatchListEntryTest extends GerritBaseTests {
   @Test
   public void empty1() {
     final String name = "empty-file";
diff --git a/javatests/com/google/gerrit/server/patch/PatchListTest.java b/javatests/com/google/gerrit/server/patch/PatchListTest.java
index 6fbafb6..ccdd040 100644
--- a/javatests/com/google/gerrit/server/patch/PatchListTest.java
+++ b/javatests/com/google/gerrit/server/patch/PatchListTest.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -25,7 +26,7 @@
 import java.util.Arrays;
 import org.junit.Test;
 
-public class PatchListTest {
+public class PatchListTest extends GerritBaseTests {
   @Test
   public void fileOrder() {
     String[] names = {
diff --git a/javatests/com/google/gerrit/server/permissions/DefaultPermissionsMappingTest.java b/javatests/com/google/gerrit/server/permissions/DefaultPermissionsMappingTest.java
index 305e81b..ff9ac41 100644
--- a/javatests/com/google/gerrit/server/permissions/DefaultPermissionsMappingTest.java
+++ b/javatests/com/google/gerrit/server/permissions/DefaultPermissionsMappingTest.java
@@ -18,9 +18,10 @@
 import static com.google.gerrit.server.permissions.DefaultPermissionMappings.refPermission;
 
 import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class DefaultPermissionsMappingTest {
+public class DefaultPermissionsMappingTest extends GerritBaseTests {
   @Test
   public void stringToRefPermission() {
     assertThat(refPermission("doesnotexist")).isEmpty();
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index 38e9578..c467312 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -66,6 +66,7 @@
 import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryModule;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -89,7 +90,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class RefControlTest {
+public class RefControlTest extends GerritBaseTests {
   private void assertAdminsAreOwnersAndDevsAreNot() {
     ProjectControl uBlah = user(local, DEVS);
     ProjectControl uAdmin = user(local, DEVS, ADMIN);
diff --git a/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java b/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
index 2ae9e90..79c620a 100644
--- a/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
+++ b/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.project.testing.Util;
 import com.google.gerrit.server.restapi.project.CommitsCollection;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import com.google.gerrit.testing.InMemoryTestEnvironment;
 import com.google.inject.Inject;
@@ -48,7 +49,7 @@
 import org.junit.Test;
 
 /** Unit tests for {@link CommitsCollection}. */
-public class CommitsCollectionTest {
+public class CommitsCollectionTest extends GerritBaseTests {
   @Rule public InMemoryTestEnvironment testEnvironment = new InMemoryTestEnvironment();
 
   @Inject private AccountManager accountManager;
diff --git a/javatests/com/google/gerrit/server/project/GroupListTest.java b/javatests/com/google/gerrit/server/project/GroupListTest.java
index 2249a16..08aca9f 100644
--- a/javatests/com/google/gerrit/server/project/GroupListTest.java
+++ b/javatests/com/google/gerrit/server/project/GroupListTest.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.ValidationError;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
@@ -36,7 +37,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class GroupListTest {
+public class GroupListTest extends GerritBaseTests {
   private static final Project.NameKey PROJECT = new Project.NameKey("project");
   private static final String TEXT =
       "# UUID                                  \tGroup Name\n"
diff --git a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
index a1e0566..3436153 100644
--- a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
+++ b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
@@ -38,7 +38,6 @@
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.project.testing.Util;
 import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.TempFileUtil;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -58,9 +57,10 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.util.RawParseUtils;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 public class ProjectConfigTest extends GerritBaseTests {
   private static final String LABEL_SCORES_CONFIG =
@@ -85,6 +85,8 @@
 
   private static final AllProjectsName ALL_PROJECTS = new AllProjectsName("All-The-Projects");
 
+  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   private final GroupReference developers =
       new GroupReference(new AccountGroup.UUID("X"), "Developers");
   private final GroupReference staff = new GroupReference(new AccountGroup.UUID("Y"), "Staff");
@@ -96,18 +98,13 @@
 
   @Before
   public void setUp() throws Exception {
-    sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
+    sitePaths = new SitePaths(temporaryFolder.newFolder().toPath());
     Files.createDirectories(sitePaths.etc_dir);
     factory = new ProjectConfig.Factory(sitePaths, ALL_PROJECTS);
     db = new InMemoryRepository(new DfsRepositoryDescription("repo"));
     tr = new TestRepository<>(db);
   }
 
-  @After
-  public void tearDown() throws Exception {
-    TempFileUtil.cleanup();
-  }
-
   @Test
   public void readConfig() throws Exception {
     RevCommit rev =
diff --git a/javatests/com/google/gerrit/server/query/change/ChangeDataTest.java b/javatests/com/google/gerrit/server/query/change/ChangeDataTest.java
index c8637cd..f7252c0 100644
--- a/javatests/com/google/gerrit/server/query/change/ChangeDataTest.java
+++ b/javatests/com/google/gerrit/server/query/change/ChangeDataTest.java
@@ -21,10 +21,11 @@
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.TestChanges;
 import org.junit.Test;
 
-public class ChangeDataTest {
+public class ChangeDataTest extends GerritBaseTests {
   @Test
   public void setPatchSetsClearsCurrentPatchSet() throws Exception {
     Project.NameKey project = new Project.NameKey("project");
diff --git a/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java b/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
index de2acf0..1683b56 100644
--- a/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
+++ b/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
@@ -24,10 +24,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.server.cache.proto.Cache.ConflictKeyProto;
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
-public class ConflictKeyTest {
+public class ConflictKeyTest extends GerritBaseTests {
   @Test
   public void ffOnlyPreservesInputOrder() {
     ObjectId id1 = ObjectId.fromString("badc0feebadc0feebadc0feebadc0feebadc0fee");
diff --git a/javatests/com/google/gerrit/server/query/change/RegexPathPredicateTest.java b/javatests/com/google/gerrit/server/query/change/RegexPathPredicateTest.java
index a13a8f7..9944a42 100644
--- a/javatests/com/google/gerrit/server/query/change/RegexPathPredicateTest.java
+++ b/javatests/com/google/gerrit/server/query/change/RegexPathPredicateTest.java
@@ -19,11 +19,12 @@
 
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gwtorm.server.OrmException;
 import java.util.Arrays;
 import org.junit.Test;
 
-public class RegexPathPredicateTest {
+public class RegexPathPredicateTest extends GerritBaseTests {
   @Test
   public void prefixOnlyOptimization() throws OrmException {
     RegexPathPredicate p = predicate("^a/b/.*");
diff --git a/javatests/com/google/gerrit/server/rules/IgnoreSelfApprovalRuleTest.java b/javatests/com/google/gerrit/server/rules/IgnoreSelfApprovalRuleTest.java
index 27f4423..14124fa 100644
--- a/javatests/com/google/gerrit/server/rules/IgnoreSelfApprovalRuleTest.java
+++ b/javatests/com/google/gerrit/server/rules/IgnoreSelfApprovalRuleTest.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.reviewdb.client.LabelId;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -31,7 +32,7 @@
 import java.util.List;
 import org.junit.Test;
 
-public class IgnoreSelfApprovalRuleTest {
+public class IgnoreSelfApprovalRuleTest extends GerritBaseTests {
   private static final Change.Id CHANGE_ID = new Change.Id(100);
   private static final PatchSet.Id PS_ID = new PatchSet.Id(CHANGE_ID, 1);
   private static final LabelType VERIFIED = makeLabel("Verified");
diff --git a/javatests/com/google/gerrit/server/rules/PrologRuleEvaluatorTest.java b/javatests/com/google/gerrit/server/rules/PrologRuleEvaluatorTest.java
index 8622b32..6eb0747 100644
--- a/javatests/com/google/gerrit/server/rules/PrologRuleEvaluatorTest.java
+++ b/javatests/com/google/gerrit/server/rules/PrologRuleEvaluatorTest.java
@@ -16,9 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class PrologRuleEvaluatorTest {
+public class PrologRuleEvaluatorTest extends GerritBaseTests {
 
   @Test
   public void validLabelNamesAreKept() {
diff --git a/javatests/com/google/gerrit/server/schema/HANATest.java b/javatests/com/google/gerrit/server/schema/HANATest.java
index ac58134..ccf747f 100644
--- a/javatests/com/google/gerrit/server/schema/HANATest.java
+++ b/javatests/com/google/gerrit/server/schema/HANATest.java
@@ -15,11 +15,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Before;
 import org.junit.Test;
 
-public class HANATest {
+public class HANATest extends GerritBaseTests {
 
   private HANA hana;
   private Config config;
diff --git a/javatests/com/google/gerrit/server/schema/ProjectConfigSchemaUpdateTest.java b/javatests/com/google/gerrit/server/schema/ProjectConfigSchemaUpdateTest.java
index de825e6..e4089c5 100644
--- a/javatests/com/google/gerrit/server/schema/ProjectConfigSchemaUpdateTest.java
+++ b/javatests/com/google/gerrit/server/schema/ProjectConfigSchemaUpdateTest.java
@@ -22,7 +22,6 @@
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.testing.TempFileUtil;
 import java.io.File;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -33,20 +32,23 @@
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.util.FS;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 public class ProjectConfigSchemaUpdateTest {
   private static final String ALL_PROJECTS = "All-The-Projects";
 
+  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
   private SitePaths sitePaths;
   private ProjectConfigSchemaUpdate.Factory factory;
   private File allProjectsRepoFile;
 
   @Before
   public void setUp() throws Exception {
-    sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
+    sitePaths = new SitePaths(temporaryFolder.newFolder().toPath());
     Files.createDirectories(sitePaths.etc_dir);
 
     Path gitPath = sitePaths.resolve("git");
@@ -66,11 +68,6 @@
     factory = new ProjectConfigSchemaUpdate.Factory(sitePaths, new AllProjectsName(ALL_PROJECTS));
   }
 
-  @After
-  public void tearDown() throws Exception {
-    TempFileUtil.cleanup();
-  }
-
   @Test
   public void noBaseConfig() throws Exception {
     assertThat(getConfig().getString("foo", null, "bar")).isNull();
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
index bb358cc..fa0d8b3 100644
--- a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
+++ b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.ProjectConfig;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryModule;
 import com.google.gwtorm.jdbc.JdbcSchema;
@@ -42,7 +43,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class ReviewDbSchemaCreatorTest {
+public class ReviewDbSchemaCreatorTest extends GerritBaseTests {
   @Inject private AllProjectsName allProjects;
 
   @Inject private GitRepositoryManager repoManager;
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
index 4133558..55bd5f9 100644
--- a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
+++ b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.group.SystemGroupBackend;
 import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryH2Type;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -55,7 +56,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class ReviewDbSchemaUpdaterTest {
+public class ReviewDbSchemaUpdaterTest extends GerritBaseTests {
   private LifecycleManager lifecycle;
   private InMemoryDatabase db;
 
diff --git a/javatests/com/google/gerrit/server/update/BatchUpdateTest.java b/javatests/com/google/gerrit/server/update/BatchUpdateTest.java
index 70c4383..7f8e1f4 100644
--- a/javatests/com/google/gerrit/server/update/BatchUpdateTest.java
+++ b/javatests/com/google/gerrit/server/update/BatchUpdateTest.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryTestEnvironment;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -31,7 +32,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-public class BatchUpdateTest {
+public class BatchUpdateTest extends GerritBaseTests {
   @Rule public InMemoryTestEnvironment testEnvironment = new InMemoryTestEnvironment();
 
   @Inject private GitRepositoryManager repoManager;
diff --git a/javatests/com/google/gerrit/server/update/RepoViewTest.java b/javatests/com/google/gerrit/server/update/RepoViewTest.java
index 9f7deee..b41c66c 100644
--- a/javatests/com/google/gerrit/server/update/RepoViewTest.java
+++ b/javatests/com/google/gerrit/server/update/RepoViewTest.java
@@ -19,6 +19,7 @@
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.Config;
@@ -30,7 +31,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-public class RepoViewTest {
+public class RepoViewTest extends GerritBaseTests {
   private static final String MASTER = "refs/heads/master";
   private static final String BRANCH = "refs/heads/branch";
 
diff --git a/javatests/com/google/gerrit/server/util/IdGeneratorTest.java b/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
index 808eca8..e702656 100644
--- a/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
+++ b/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
@@ -17,10 +17,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.HashSet;
 import org.junit.Test;
 
-public class IdGeneratorTest {
+public class IdGeneratorTest extends GerritBaseTests {
   @Test
   public void test1234() {
     final HashSet<Integer> seen = new HashSet<>();
diff --git a/javatests/com/google/gerrit/server/util/LabelVoteTest.java b/javatests/com/google/gerrit/server/util/LabelVoteTest.java
index 9069928..3048b75 100644
--- a/javatests/com/google/gerrit/server/util/LabelVoteTest.java
+++ b/javatests/com/google/gerrit/server/util/LabelVoteTest.java
@@ -19,9 +19,10 @@
 import static com.google.gerrit.server.util.LabelVote.parse;
 import static com.google.gerrit.server.util.LabelVote.parseWithEquals;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class LabelVoteTest {
+public class LabelVoteTest extends GerritBaseTests {
   @Test
   public void labelVoteParse() {
     assertLabelVoteEquals(parse("Code-Review-2"), "Code-Review", -2);
diff --git a/javatests/com/google/gerrit/server/util/MostSpecificComparatorTest.java b/javatests/com/google/gerrit/server/util/MostSpecificComparatorTest.java
index 025bf84..9ea17f3 100644
--- a/javatests/com/google/gerrit/server/util/MostSpecificComparatorTest.java
+++ b/javatests/com/google/gerrit/server/util/MostSpecificComparatorTest.java
@@ -16,9 +16,10 @@
 
 import static org.junit.Assert.assertTrue;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import org.junit.Test;
 
-public class MostSpecificComparatorTest {
+public class MostSpecificComparatorTest extends GerritBaseTests {
 
   private MostSpecificComparator cmp;
 
diff --git a/javatests/com/google/gerrit/server/util/git/BUILD b/javatests/com/google/gerrit/server/util/git/BUILD
index 61a776fa..096afa6 100644
--- a/javatests/com/google/gerrit/server/util/git/BUILD
+++ b/javatests/com/google/gerrit/server/util/git/BUILD
@@ -10,6 +10,7 @@
     deps = [
         "//java/com/google/gerrit/reviewdb:server",
         "//java/com/google/gerrit/server/util/git",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//java/com/google/gerrit/truth",
         "//java/org/eclipse/jgit:server",
         "//lib:gson",
diff --git a/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java b/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
index 0ec9b38..c5e683f 100644
--- a/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
+++ b/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
@@ -20,11 +20,12 @@
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Set;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
-public class SubmoduleSectionParserTest {
+public class SubmoduleSectionParserTest extends GerritBaseTests {
   private static final String THIS_SERVER = "http://localhost/";
 
   @Test
diff --git a/javatests/com/google/gerrit/sshd/BUILD b/javatests/com/google/gerrit/sshd/BUILD
index ad7d8a9..7a5e18e 100644
--- a/javatests/com/google/gerrit/sshd/BUILD
+++ b/javatests/com/google/gerrit/sshd/BUILD
@@ -7,6 +7,7 @@
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/sshd",
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib/mina:sshd",
         "//lib/truth",
     ],
diff --git a/javatests/com/google/gerrit/sshd/commands/ProjectConfigParamParserTest.java b/javatests/com/google/gerrit/sshd/commands/ProjectConfigParamParserTest.java
index 777cb4f..b663849 100644
--- a/javatests/com/google/gerrit/sshd/commands/ProjectConfigParamParserTest.java
+++ b/javatests/com/google/gerrit/sshd/commands/ProjectConfigParamParserTest.java
@@ -17,12 +17,13 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.extensions.api.projects.ConfigValue;
+import com.google.gerrit.testing.GerritBaseTests;
 import java.util.Collections;
 import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 
-public class ProjectConfigParamParserTest {
+public class ProjectConfigParamParserTest extends GerritBaseTests {
 
   private CreateProjectCommand cmd;
 
diff --git a/javatests/com/google/gerrit/util/http/BUILD b/javatests/com/google/gerrit/util/http/BUILD
index 48b4339..2999fc0 100644
--- a/javatests/com/google/gerrit/util/http/BUILD
+++ b/javatests/com/google/gerrit/util/http/BUILD
@@ -4,6 +4,7 @@
     name = "http_tests",
     srcs = glob(["**/*.java"]),
     deps = [
+        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//java/com/google/gerrit/util/http",
         "//javatests/com/google/gerrit/util/http/testutil",
         "//lib:junit",
diff --git a/javatests/com/google/gerrit/util/http/RequestUtilTest.java b/javatests/com/google/gerrit/util/http/RequestUtilTest.java
index 48b7b9c..0bf34e7 100644
--- a/javatests/com/google/gerrit/util/http/RequestUtilTest.java
+++ b/javatests/com/google/gerrit/util/http/RequestUtilTest.java
@@ -16,10 +16,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
 import org.junit.Test;
 
-public class RequestUtilTest {
+public class RequestUtilTest extends GerritBaseTests {
   @Test
   public void emptyContextPath() {
     assertThat(RequestUtil.getEncodedPathInfo(fakeRequest("", "/s", "/foo/bar")))
diff --git a/polygerrit-ui/app/elements/diff/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.html b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.html
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.html
rename to polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.html
diff --git a/polygerrit-ui/app/elements/diff/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js
rename to polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js