You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ep...@apache.org on 2023/03/30 19:23:29 UTC

[solr] branch main updated: SOLR-16604: Use the Builders directly in unit tests (#1499)

This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 288e5123dec SOLR-16604: Use the Builders directly in unit tests (#1499)
288e5123dec is described below

commit 288e5123dec8f604fe57a9cb13e9770001c0ed57
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Thu Mar 30 15:23:23 2023 -0400

    SOLR-16604: Use the Builders directly in unit tests (#1499)
    
    Use the Solr Client Builders in the unit tests instead of the SolrTestCaseJ4 methods unless it's the most common simplistic method.
---
 solr/CHANGES.txt                                   |   2 +
 .../client/solrj/impl/ConnectionReuseTest.java     |  10 +-
 .../apache/solr/cloud/AliasIntegrationTest.java    |   8 +-
 .../apache/solr/cloud/CreateRoutedAliasTest.java   |  27 +--
 .../solr/cloud/DistributedVersionInfoTest.java     |   8 +-
 .../solr/cloud/FullSolrCloudDistribCmdsTest.java   |   7 +-
 .../org/apache/solr/cloud/SSLMigrationTest.java    |   4 +-
 .../solr/cloud/TestMiniSolrCloudClusterSSL.java    |   2 -
 .../org/apache/solr/cloud/TestPullReplica.java     |  10 +-
 .../solr/cloud/TestRandomRequestDistribution.java  |  13 +-
 .../org/apache/solr/cloud/TestTlogReplica.java     |  10 +-
 .../solr/cloud/api/collections/ShardSplitTest.java |   6 +-
 .../TestRequestStatusCollectionAPI.java            |   7 +-
 .../solr/core/snapshots/TestSolrCoreSnapshots.java |   5 +-
 .../apache/solr/handler/ReplicationTestHelper.java |   7 +-
 .../solr/handler/TestReplicationHandlerBackup.java |   7 +-
 .../org/apache/solr/handler/TestRestoreCore.java   |   7 +-
 .../solr/handler/admin/AdminHandlersProxyTest.java |  19 +-
 .../solr/handler/admin/CoreAdminHandlerTest.java   |  82 ++++----
 .../src/test/org/apache/solr/search/TestSolrJ.java |   7 +-
 .../CategoryRoutedAliasUpdateProcessorTest.java    |  18 +-
 .../DimensionalRoutedAliasUpdateProcessorTest.java |  17 +-
 .../processor/RoutedAliasUpdateProcessorTest.java  |  81 ++++---
 .../TimeRoutedAliasUpdateProcessorTest.java        |  11 +-
 .../org/apache/solr/hdfs/cloud/StressHdfsTest.java |   5 +-
 .../apache/solr/common/cloud/SolrZkClientTest.java |   6 +-
 .../solr/client/solrj/SolrExceptionTest.java       |   9 +-
 .../solr/client/solrj/TestLBHttpSolrClient.java    |   4 +-
 .../solrj/embedded/SolrExampleJettyTest.java       |   3 +-
 .../client/solrj/impl/BasicHttpSolrClientTest.java |  17 +-
 .../impl/CloudHttp2SolrClientBadInputTest.java     |   2 +-
 .../solrj/impl/CloudHttp2SolrClientTest.java       |  22 +-
 .../solrj/impl/CloudSolrClientBadInputTest.java    |  51 +++--
 .../client/solrj/impl/CloudSolrClientTest.java     |  22 +-
 .../ConcurrentUpdateSolrClientBadInputTest.java    |  14 +-
 .../client/solrj/impl/Http2SolrClientTest.java     |  17 +-
 .../solrj/impl/LBHttpSolrClientBadInputTest.java   |   7 +-
 .../java/org/apache/solr/SolrJettyTestBase.java    |   2 +-
 .../src/java/org/apache/solr/SolrTestCaseJ4.java   | 234 ---------------------
 .../cloud/AbstractBasicDistributedZkTestBase.java  |  16 +-
 .../solr/cloud/AbstractFullDistribZkTestBase.java  |  33 ++-
 .../solr/cloud/AbstractSyncSliceTestBase.java      |   6 +-
 .../cloud/AbstractUnloadDistributedZkTestBase.java |  35 +--
 .../org/apache/solr/cloud/SolrCloudTestCase.java   |   7 +-
 44 files changed, 377 insertions(+), 510 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 8e89a1f8b34..fb2c9233f94 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -105,6 +105,8 @@ Other Changes
 
 * SOLR-16715: Replace new HashMap(int) and new HashSet(int) with CollectionUtil.newHashMap / CollectionUtil.newHashSet (Kevin Risden)
 
+* SOLR-16604: Use Solr Client Builders directly in unit tests instead of delegating to SolrTestCaseJ4. (Eric Pugh, David Smiley)
+
 ==================  9.2.0 ==================
 
 New Features
diff --git a/solr/core/src/test/org/apache/solr/client/solrj/impl/ConnectionReuseTest.java b/solr/core/src/test/org/apache/solr/client/solrj/impl/ConnectionReuseTest.java
index ee990406165..e68ea8722bf 100644
--- a/solr/core/src/test/org/apache/solr/client/solrj/impl/ConnectionReuseTest.java
+++ b/solr/core/src/test/org/apache/solr/client/solrj/impl/ConnectionReuseTest.java
@@ -83,9 +83,15 @@ public class ConnectionReuseTest extends SolrCloudTestCase {
     switch (random().nextInt(3)) {
       case 0:
         // currently, only testing with 1 thread
-        return getConcurrentUpdateSolrClient(url.toString() + "/" + COLLECTION, httpClient, 6, 1);
+        return new ConcurrentUpdateSolrClient.Builder(url.toString() + "/" + COLLECTION)
+            .withHttpClient(httpClient)
+            .withQueueSize(6)
+            .withThreadCount(1)
+            .build();
       case 1:
-        return getHttpSolrClient(url.toString() + "/" + COLLECTION, httpClient);
+        return new HttpSolrClient.Builder(url.toString() + "/" + COLLECTION)
+            .withHttpClient(httpClient)
+            .build();
       case 2:
         var builder =
             new RandomizingCloudSolrClientBuilder(
diff --git a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
index a4061f7ad87..f59c72a3392 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
@@ -34,7 +34,6 @@ import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.util.EntityUtils;
-import org.apache.lucene.util.IOUtils;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
@@ -69,7 +68,6 @@ import org.junit.Test;
 public class AliasIntegrationTest extends SolrCloudTestCase {
 
   private CloseableHttpClient httpClient;
-  private CloudSolrClient solrClient;
 
   @BeforeClass
   public static void setupCluster() throws Exception {
@@ -80,15 +78,15 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
   @Override
   public void setUp() throws Exception {
     super.setUp();
-    solrClient = getCloudSolrClient(cluster);
-    httpClient = (CloseableHttpClient) ((CloudLegacySolrClient) solrClient).getHttpClient();
+
+    httpClient =
+        (CloseableHttpClient) ((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient();
   }
 
   @After
   @Override
   public void tearDown() throws Exception {
     super.tearDown();
-    IOUtils.close(solrClient, httpClient);
 
     cluster.deleteAllCollections(); // note: deletes aliases too
   }
diff --git a/solr/core/src/test/org/apache/solr/cloud/CreateRoutedAliasTest.java b/solr/core/src/test/org/apache/solr/cloud/CreateRoutedAliasTest.java
index a7801eadb65..e960a8ea178 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CreateRoutedAliasTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CreateRoutedAliasTest.java
@@ -36,7 +36,6 @@ import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.util.EntityUtils;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -76,17 +75,12 @@ public class CreateRoutedAliasTest extends SolrCloudTestCase {
 
   @Before
   public void doBefore() {
-    solrClient = getCloudSolrClient(cluster);
+    solrClient = cluster.getSolrClient();
   }
 
   @After
   public void doAfter() throws Exception {
     cluster.deleteAllCollections(); // deletes aliases too
-
-    if (null != solrClient) {
-      solrClient.close();
-      solrClient = null;
-    }
   }
 
   // This is a fairly complete test where we set many options and see that it both affected the
@@ -321,16 +315,15 @@ public class CreateRoutedAliasTest extends SolrCloudTestCase {
   @Test
   public void testTimezoneAbsoluteDate() throws Exception {
     final String aliasName = getSaferTestName();
-    try (SolrClient client = getCloudSolrClient(cluster)) {
-      CollectionAdminRequest.createTimeRoutedAlias(
-              aliasName,
-              "2018-01-15T00:00:00Z",
-              "+30MINUTE",
-              "evt_dt",
-              CollectionAdminRequest.createCollection("_ignored_", "_default", 1, 1))
-          .setTimeZone(TimeZone.getTimeZone("GMT-10"))
-          .process(client);
-    }
+
+    CollectionAdminRequest.createTimeRoutedAlias(
+            aliasName,
+            "2018-01-15T00:00:00Z",
+            "+30MINUTE",
+            "evt_dt",
+            CollectionAdminRequest.createCollection("_ignored_", "_default", 1, 1))
+        .setTimeZone(TimeZone.getTimeZone("GMT-10"))
+        .process(solrClient);
 
     assertCollectionExists(aliasName + TIME.getSeparatorPrefix() + "2018-01-15");
   }
diff --git a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
index d2864f469ec..c04c7939e64 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
@@ -323,9 +323,9 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
       int lastDocId,
       Set<Integer> deletedDocs)
       throws Exception {
-    SolrClient leaderSolr = getSolrClient(leader);
+    SolrClient leaderSolr = getHttpSolrClient(leader.getCoreUrl());
     List<SolrClient> replicas = new ArrayList<SolrClient>(notLeaders.size());
-    for (Replica r : notLeaders) replicas.add(getSolrClient(r));
+    for (Replica r : notLeaders) replicas.add(getHttpSolrClient(r.getCoreUrl()));
 
     try {
       for (int d = firstDocId; d <= lastDocId; d++) {
@@ -348,10 +348,6 @@ public class DistributedVersionInfoTest extends SolrCloudTestCase {
     }
   }
 
-  protected SolrClient getSolrClient(Replica replica) {
-    return getHttpSolrClient(replica.getCoreUrl());
-  }
-
   protected void sendDoc(int docId) throws Exception {
     SolrInputDocument doc = new SolrInputDocument();
     doc.addField("id", String.valueOf(docId));
diff --git a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
index 5ad626d7a79..6a9bf85a22c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
@@ -779,8 +779,11 @@ public class FullSolrCloudDistribCmdsTest extends SolrCloudTestCase {
     final int numDocs = atLeast(50);
     final JettySolrRunner nodeToUpdate = cluster.getRandomJetty(random());
     try (ConcurrentUpdateSolrClient indexClient =
-        getConcurrentUpdateSolrClient(
-            nodeToUpdate.getProxyBaseUrl() + "/" + collectionName, 10, 2)) {
+        new ConcurrentUpdateSolrClient.Builder(
+                nodeToUpdate.getProxyBaseUrl() + "/" + collectionName)
+            .withQueueSize(10)
+            .withThreadCount(2)
+            .build()) {
 
       for (int i = 0; i < numDocs; i++) {
         indexClient.add(
diff --git a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
index 56262d44d6e..8bd7cd3fd9a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
@@ -26,6 +26,7 @@ import org.apache.lucene.tests.util.LuceneTestCase.AwaitsFix;
 import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.cloud.DocCollection;
 import org.apache.solr.common.cloud.Replica;
@@ -128,7 +129,8 @@ public class SSLMigrationTest extends AbstractFullDistribZkTestBase {
       urls.add(replica.getStr(ZkStateReader.BASE_URL_PROP));
     }
     // Create new SolrServer to configure new HttpClient w/ SSL config
-    try (SolrClient client = getLBHttpSolrClient(urls.toArray(new String[] {}))) {
+    try (SolrClient client =
+        new LBHttpSolrClient.Builder().withBaseSolrUrls(urls.toArray(new String[] {})).build()) {
       client.request(request);
     }
   }
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
index c2734a92616..ca516cdfb05 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
@@ -418,8 +418,6 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 {
   /**
    * Generates an HttpSolrClient, either by using the test framework helper method or by direct
    * instantiation (determined randomly)
-   *
-   * @see #getHttpSolrClient
    */
   public static SolrClient getRandomizedHttpSolrClient(String url) {
     // NOTE: at the moment, SolrTestCaseJ4 already returns "new HttpSolrClient" most of the time,
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
index 4bc91c74b0d..6b5da5ea181 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java
@@ -37,6 +37,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
@@ -462,14 +463,16 @@ public class TestPullReplica extends SolrCloudTestCase {
     Slice slice = docCollection.getSlice("shard1");
     List<String> ids = new ArrayList<>(slice.getReplicas().size());
     for (Replica rAdd : slice.getReplicas()) {
-      try (SolrClient client = getHttpSolrClient(rAdd.getCoreUrl(), httpClient)) {
+      try (SolrClient client =
+          new HttpSolrClient.Builder(rAdd.getCoreUrl()).withHttpClient(httpClient).build()) {
         client.add(new SolrInputDocument("id", String.valueOf(id), "foo_s", "bar"));
       }
       SolrDocument docCloudClient =
           cluster.getSolrClient().getById(collectionName, String.valueOf(id));
       assertEquals("bar", docCloudClient.getFieldValue("foo_s"));
       for (Replica rGet : slice.getReplicas()) {
-        try (SolrClient client = getHttpSolrClient(rGet.getCoreUrl(), httpClient)) {
+        try (SolrClient client =
+            new HttpSolrClient.Builder(rGet.getCoreUrl()).withHttpClient(httpClient).build()) {
           SolrDocument doc = client.getById(String.valueOf(id));
           assertEquals("bar", doc.getFieldValue("foo_s"));
         }
@@ -479,7 +482,8 @@ public class TestPullReplica extends SolrCloudTestCase {
     }
     SolrDocumentList previousAllIdsResult = null;
     for (Replica rAdd : slice.getReplicas()) {
-      try (SolrClient client = getHttpSolrClient(rAdd.getCoreUrl(), httpClient)) {
+      try (SolrClient client =
+          new HttpSolrClient.Builder(rAdd.getCoreUrl()).withHttpClient(httpClient).build()) {
         SolrDocumentList allIdsResult = client.getById(ids);
         if (previousAllIdsResult != null) {
           assertTrue(compareSolrDocumentList(previousAllIdsResult, allIdsResult));
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
index 0681207747c..768f258cc50 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
@@ -31,6 +31,7 @@ import org.apache.solr.BaseDistributedSearchTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.cloud.overseer.OverseerAction;
 import org.apache.solr.common.cloud.ClusterState;
@@ -108,7 +109,11 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
     assertEquals(1, replicas.size());
     String baseUrl = replicas.iterator().next().getBaseUrl();
     if (!baseUrl.endsWith("/")) baseUrl += "/";
-    try (SolrClient client = getHttpSolrClient(baseUrl + "a1x2", 2000, 5000)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(baseUrl + "a1x2")
+            .withConnectionTimeout(2000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(5000, TimeUnit.MILLISECONDS)
+            .build()) {
 
       long expectedTotalRequests = 0;
       Set<String> uniqueCoreNames = new LinkedHashSet<>();
@@ -219,7 +224,11 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
     if (!baseUrl.endsWith("/")) baseUrl += "/";
     String path = baseUrl + "football";
     log.info("Firing queries against path={}", path);
-    try (SolrClient client = getHttpSolrClient(path, 2000, 5000)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(path)
+            .withConnectionTimeout(2000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(5000, TimeUnit.MILLISECONDS)
+            .build()) {
 
       SolrCore leaderCore = null;
       for (JettySolrRunner jetty : jettys) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
index 887f093c001..39a8130903d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTlogReplica.java
@@ -44,6 +44,7 @@ import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -399,7 +400,8 @@ public class TestTlogReplica extends SolrCloudTestCase {
     Slice slice = docCollection.getSlice("shard1");
     List<String> ids = new ArrayList<>(slice.getReplicas().size());
     for (Replica rAdd : slice.getReplicas()) {
-      try (SolrClient client = getHttpSolrClient(rAdd.getCoreUrl(), httpClient)) {
+      try (SolrClient client =
+          new HttpSolrClient.Builder(rAdd.getCoreUrl()).withHttpClient(httpClient).build()) {
         client.add(new SolrInputDocument("id", String.valueOf(id), "foo_s", "bar"));
       }
       SolrDocument docCloudClient =
@@ -407,7 +409,8 @@ public class TestTlogReplica extends SolrCloudTestCase {
       assertNotNull(docCloudClient);
       assertEquals("bar", docCloudClient.getFieldValue("foo_s"));
       for (Replica rGet : slice.getReplicas()) {
-        try (SolrClient client = getHttpSolrClient(rGet.getCoreUrl(), httpClient)) {
+        try (SolrClient client =
+            new HttpSolrClient.Builder(rGet.getCoreUrl()).withHttpClient(httpClient).build()) {
           SolrDocument doc = client.getById(String.valueOf(id));
           assertEquals("bar", doc.getFieldValue("foo_s"));
         }
@@ -417,7 +420,8 @@ public class TestTlogReplica extends SolrCloudTestCase {
     }
     SolrDocumentList previousAllIdsResult = null;
     for (Replica rAdd : slice.getReplicas()) {
-      try (SolrClient client = getHttpSolrClient(rAdd.getCoreUrl(), httpClient)) {
+      try (SolrClient client =
+          new HttpSolrClient.Builder(rAdd.getCoreUrl()).withHttpClient(httpClient).build()) {
         SolrDocumentList allIdsResult = client.getById(ids);
         if (previousAllIdsResult != null) {
           assertTrue(compareSolrDocumentList(previousAllIdsResult, allIdsResult));
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
index da5ce1b7cbb..9eccd8eefc8 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java
@@ -1268,7 +1268,11 @@ public class ShardSplitTest extends BasicDistributedZkTest {
         ((HttpSolrClient) shardToJetty.get(SHARD1).get(0).client.getSolrClient()).getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (SolrClient baseServer = getHttpSolrClient(baseUrl, 30000, 60000 * 5)) {
+    try (SolrClient baseServer =
+        new HttpSolrClient.Builder(baseUrl)
+            .withConnectionTimeout(30, TimeUnit.SECONDS)
+            .withSocketTimeout(5, TimeUnit.MINUTES)
+            .build()) {
       NamedList<Object> rsp = baseServer.request(request);
       if (log.isInfoEnabled()) {
         log.info("Shard split response: {}", Utils.toJSONString(rsp));
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java
index e5545ee8eab..57a952f5f7a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java
@@ -20,8 +20,10 @@ import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.RequestStatusState;
 import org.apache.solr.cloud.BasicDistributedZkTest;
@@ -223,7 +225,10 @@ public class TestRequestStatusCollectionAPI extends BasicDistributedZkTest {
 
     String baseUrl = shardToJetty.get(SHARD1).get(0).jetty.getBaseUrl().toString();
 
-    try (SolrClient baseServer = getHttpSolrClient(baseUrl, 15000)) {
+    try (SolrClient baseServer =
+        new HttpSolrClient.Builder(baseUrl)
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .build()) {
       return baseServer.request(request);
     }
   }
diff --git a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
index 5f30ea1051c..399ec7a6905 100644
--- a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
+++ b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCoreSnapshots.java
@@ -34,6 +34,7 @@ import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.Http2SolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.CreateSnapshot;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.DeleteSnapshot;
@@ -108,7 +109,7 @@ public class TestSolrCoreSnapshots extends SolrCloudTestCase {
 
     try (SolrClient adminClient =
             getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
-        SolrClient leaderClient = getHttpSolrClient(replica.getCoreUrl())) {
+        SolrClient leaderClient = new Http2SolrClient.Builder(replica.getCoreUrl()).build()) {
 
       SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
       // Create another snapshot referring to the same index commit to verify the
@@ -199,7 +200,7 @@ public class TestSolrCoreSnapshots extends SolrCloudTestCase {
 
     try (SolrClient adminClient =
             getHttpSolrClient(cluster.getJettySolrRunners().get(0).getBaseUrl().toString());
-        SolrClient leaderClient = getHttpSolrClient(replica.getCoreUrl())) {
+        SolrClient leaderClient = new Http2SolrClient.Builder(replica.getCoreUrl()).build()) {
 
       SnapshotMetaData metaData = createSnapshot(adminClient, coreName, commitName);
 
diff --git a/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java b/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
index 7c1eb858244..83b60838b06 100644
--- a/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
+++ b/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
@@ -27,10 +27,12 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Properties;
+import java.util.concurrent.TimeUnit;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.SolrDocumentList;
@@ -63,7 +65,10 @@ public final class ReplicationTestHelper {
   }
 
   public static SolrClient createNewSolrClient(String baseUrl) {
-    return SolrTestCaseJ4.getHttpSolrClient(baseUrl, 15000, 90000);
+    return new HttpSolrClient.Builder(baseUrl)
+        .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+        .withSocketTimeout(90000, TimeUnit.MILLISECONDS)
+        .build();
   }
 
   public static int index(SolrClient s, Object... fields) throws Exception {
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
index 2af23d1a530..aff53aa66e3 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
+import java.util.concurrent.TimeUnit;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.IndexSearcher;
@@ -41,6 +42,7 @@ import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.SolrJettyTestBase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.embedded.JettyConfig;
 import org.apache.solr.embedded.JettySolrRunner;
 import org.apache.solr.util.FileUtils;
@@ -84,7 +86,10 @@ public class TestReplicationHandlerBackup extends SolrJettyTestBase {
 
   private static SolrClient createNewSolrClient(int port) {
     final String baseUrl = buildUrl(port, context);
-    return getHttpSolrClient(baseUrl, 15000, 60000);
+    return new HttpSolrClient.Builder(baseUrl)
+        .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+        .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+        .build();
   }
 
   @Override
diff --git a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
index 09f8ab7f250..553bf5912d3 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
@@ -24,12 +24,14 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Properties;
+import java.util.concurrent.TimeUnit;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.SolrJettyTestBase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.embedded.JettyConfig;
 import org.apache.solr.embedded.JettySolrRunner;
@@ -69,7 +71,10 @@ public class TestRestoreCore extends SolrJettyTestBase {
   private static SolrClient createNewSolrClient(int port) {
 
     final String baseUrl = buildUrl(port, context);
-    return getHttpSolrClient(baseUrl, 15000, 60000);
+    return new HttpSolrClient.Builder(baseUrl)
+        .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+        .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+        .build();
   }
 
   @Override
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java b/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
index d479a1bec08..b6f74ddfba6 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
@@ -20,9 +20,7 @@ package org.apache.solr.handler.admin;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.lucene.util.IOUtils;
+import org.apache.http.client.HttpClient;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
@@ -33,13 +31,12 @@ import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.util.NamedList;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class AdminHandlersProxyTest extends SolrCloudTestCase {
-  private CloseableHttpClient httpClient;
+  private HttpClient httpClient;
   private CloudSolrClient solrClient;
 
   @BeforeClass
@@ -52,16 +49,8 @@ public class AdminHandlersProxyTest extends SolrCloudTestCase {
   @Override
   public void setUp() throws Exception {
     super.setUp();
-    solrClient = getCloudSolrClient(cluster);
-    solrClient.connect(1000, TimeUnit.MILLISECONDS);
-    httpClient = (CloseableHttpClient) ((CloudLegacySolrClient) solrClient).getHttpClient();
-  }
-
-  @After
-  @Override
-  public void tearDown() throws Exception {
-    super.tearDown();
-    IOUtils.close(solrClient, httpClient);
+    solrClient = cluster.getSolrClient();
+    httpClient = ((CloudLegacySolrClient) solrClient).getHttpClient();
   }
 
   @Test
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
index 0c6749e383f..0ab68fc397e 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
@@ -24,12 +24,14 @@ import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.TimeUnit;
 import org.apache.commons.io.file.PathUtils;
 import org.apache.lucene.util.Constants;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.impl.BaseHttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.client.solrj.request.CoreStatus;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -304,10 +306,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     runner.start();
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl() + "/corex",
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl() + "/corex")
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       SolrInputDocument doc = new SolrInputDocument();
       doc.addField("id", "123");
       client.add(doc);
@@ -315,10 +317,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     }
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl().toString(),
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl().toString())
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false);
       req.setDeleteInstanceDir(true);
       req.setCoreName("corex");
@@ -330,10 +332,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     // 2> is deleted after rename properly.
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl().toString(),
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl().toString())
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       CoreAdminRequest.renameCore("corerename", "brand_new_core_name", client);
       Properties props = new Properties();
       try (Reader is = Files.newBufferedReader(renamePropFile, StandardCharsets.UTF_8)) {
@@ -344,10 +346,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     }
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl().toString(),
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl().toString())
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false);
       req.setDeleteInstanceDir(true);
       req.setCoreName("brand_new_core_name");
@@ -377,10 +379,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     runner.start();
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl() + "/corex",
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl() + "/corex")
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       SolrInputDocument doc = new SolrInputDocument();
       doc.addField("id", "123");
       client.add(doc);
@@ -388,19 +390,19 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     }
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl() + "/corex",
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl() + "/corex")
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       QueryResponse result = client.query(new SolrQuery("id:*"));
       assertEquals(1, result.getResults().getNumFound());
     }
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl().toString(),
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl().toString())
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false);
       req.setDeleteInstanceDir(false); // random().nextBoolean());
       req.setCoreName("corex");
@@ -412,10 +414,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
             BaseHttpSolrClient.RemoteSolrException.class,
             () -> {
               try (SolrClient client =
-                  getHttpSolrClient(
-                      runner.getBaseUrl() + "/corex",
-                      DEFAULT_CONNECTION_TIMEOUT,
-                      DEFAULT_CONNECTION_TIMEOUT * 1000)) {
+                  new HttpSolrClient.Builder(runner.getBaseUrl() + "/corex")
+                      .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+                      .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT * 1000, TimeUnit.MILLISECONDS)
+                      .build()) {
                 client.query(new SolrQuery("id:*"));
               } finally {
                 runner.stop();
@@ -439,10 +441,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     runner.start();
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl() + "/corex",
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl() + "/corex")
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       SolrInputDocument doc = new SolrInputDocument();
       doc.addField("id", "123");
       client.add(doc);
@@ -465,10 +467,10 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
         StandardCopyOption.REPLACE_EXISTING);
 
     try (SolrClient client =
-        getHttpSolrClient(
-            runner.getBaseUrl().toString(),
-            DEFAULT_CONNECTION_TIMEOUT,
-            DEFAULT_CONNECTION_TIMEOUT)) {
+        new HttpSolrClient.Builder(runner.getBaseUrl().toString())
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .build()) {
       // this is expected because we put a bad solrconfig -- ignore
       expectThrows(Exception.class, () -> CoreAdminRequest.reloadCore("corex", client));
 
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
index c131f075813..3f275673f35 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
@@ -59,7 +59,12 @@ public class TestSolrJ extends SolrTestCaseJ4 {
     ConcurrentUpdateSolrClient concurrentClient = null;
 
     // server = concurrentClient = new ConcurrentUpdateSolrServer(addr,32,8);
-    client = concurrentClient = getConcurrentUpdateSolrClient(addr, 64, nConnections);
+    client =
+        concurrentClient =
+            new ConcurrentUpdateSolrClient.Builder(addr)
+                .withQueueSize(64)
+                .withThreadCount(nConnections)
+                .build();
 
     client.deleteByQuery("*:*");
     client.commit();
diff --git a/solr/core/src/test/org/apache/solr/update/processor/CategoryRoutedAliasUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/update/processor/CategoryRoutedAliasUpdateProcessorTest.java
index ee0f599e621..4f113a8d46b 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/CategoryRoutedAliasUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/CategoryRoutedAliasUpdateProcessorTest.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import org.apache.lucene.util.IOUtils;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
@@ -38,8 +37,6 @@ import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.update.UpdateCommand;
 import org.apache.solr.util.LogLevel;
-import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -67,7 +64,7 @@ public class CategoryRoutedAliasUpdateProcessorTest extends RoutedAliasUpdatePro
   @Before
   public void doBefore() throws Exception {
     configureCluster(1).configure();
-    solrClient = getCloudSolrClient(cluster);
+    solrClient = cluster.getSolrClient();
     // log this to help debug potential causes of problems
     if (log.isInfoEnabled()) {
       log.info("SolrClient: {}", solrClient);
@@ -75,19 +72,6 @@ public class CategoryRoutedAliasUpdateProcessorTest extends RoutedAliasUpdatePro
     }
   }
 
-  @After
-  public void doAfter() throws Exception {
-    IOUtils.close(solrClient);
-    if (null != cluster) {
-      shutdownCluster();
-    }
-  }
-
-  @AfterClass
-  public static void cleanUpAfterClass() {
-    solrClient = null;
-  }
-
   @Test
   public void testNonEnglish() throws Exception {
     // test to document the expected behavior with non-english text for categories
diff --git a/solr/core/src/test/org/apache/solr/update/processor/DimensionalRoutedAliasUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/update/processor/DimensionalRoutedAliasUpdateProcessorTest.java
index 25237a153a5..48455847501 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/DimensionalRoutedAliasUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/DimensionalRoutedAliasUpdateProcessorTest.java
@@ -27,7 +27,6 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
-import org.apache.lucene.util.IOUtils;
 import org.apache.solr.client.solrj.RoutedAliasTypes;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -44,8 +43,6 @@ import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.SolrParams;
-import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -68,7 +65,7 @@ public class DimensionalRoutedAliasUpdateProcessorTest extends RoutedAliasUpdate
   @Before
   public void doBefore() throws Exception {
     configureCluster(4).configure();
-    solrClient = getCloudSolrClient(cluster);
+    solrClient = cluster.getSolrClient();
     // log this to help debug potential causes of problems
     if (log.isInfoEnabled()) {
       log.info("SolrClient: {}", solrClient);
@@ -76,18 +73,6 @@ public class DimensionalRoutedAliasUpdateProcessorTest extends RoutedAliasUpdate
     }
   }
 
-  @After
-  public void doAfter() throws Exception {
-    solrClient.close();
-    shutdownCluster();
-  }
-
-  @AfterClass
-  public static void finish() throws Exception {
-    IOUtils.close(solrClient);
-    solrClient = null;
-  }
-
   @Test
   public void testTimeCat() throws Exception {
     String configName = getSaferTestName();
diff --git a/solr/core/src/test/org/apache/solr/update/processor/RoutedAliasUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/update/processor/RoutedAliasUpdateProcessorTest.java
index cbbd18b8da6..d2e442d0dd1 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/RoutedAliasUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/RoutedAliasUpdateProcessorTest.java
@@ -217,27 +217,23 @@ public abstract class RoutedAliasUpdateProcessorTest extends SolrCloudTestCase {
   }
 
   void assertRouting(int numShards, List<UpdateCommand> updateCommands) throws IOException {
-    try (CloudSolrClient cloudSolrClient = getCloudSolrClient(cluster)) {
-      ClusterStateProvider clusterStateProvider = cloudSolrClient.getClusterStateProvider();
-      clusterStateProvider.connect();
-      Set<String> leaders = getLeaderCoreNames(clusterStateProvider.getClusterState());
-      assertEquals(
-          "should have " + 3 * numShards + " leaders, " + numShards + " per collection",
-          3 * numShards,
-          leaders.size());
-
-      assertEquals(3, updateCommands.size());
-      for (UpdateCommand updateCommand : updateCommands) {
-        String node =
-            (String)
-                updateCommand
-                    .getReq()
-                    .getContext()
-                    .get(TrackingUpdateProcessorFactory.REQUEST_NODE);
-        assertTrue(
-            "Update was not routed to a leader (" + node + " not in list of leaders" + leaders,
-            leaders.contains(node));
-      }
+    CloudSolrClient cloudSolrClient = cluster.getSolrClient();
+    ClusterStateProvider clusterStateProvider = cloudSolrClient.getClusterStateProvider();
+    clusterStateProvider.connect();
+    Set<String> leaders = getLeaderCoreNames(clusterStateProvider.getClusterState());
+    assertEquals(
+        "should have " + 3 * numShards + " leaders, " + numShards + " per collection",
+        3 * numShards,
+        leaders.size());
+
+    assertEquals(3, updateCommands.size());
+    for (UpdateCommand updateCommand : updateCommands) {
+      String node =
+          (String)
+              updateCommand.getReq().getContext().get(TrackingUpdateProcessorFactory.REQUEST_NODE);
+      assertTrue(
+          "Update was not routed to a leader (" + node + " not in list of leaders" + leaders,
+          leaders.contains(node));
     }
   }
 
@@ -325,33 +321,32 @@ public abstract class RoutedAliasUpdateProcessorTest extends SolrCloudTestCase {
     if (random().nextBoolean()) {
       // Send in separate threads. Choose random collection & solrClient
       ExecutorService exec = null;
-      try (CloudSolrClient solrClient = getCloudSolrClient(cluster)) {
-        try {
-          exec =
-              ExecutorUtil.newMDCAwareFixedThreadPool(
-                  1 + random().nextInt(2), new SolrNamedThreadFactory(getSaferTestName()));
-          List<Future<UpdateResponse>> futures = new ArrayList<>(solrInputDocuments.length);
-          for (SolrInputDocument solrInputDocument : solrInputDocuments) {
-            String col = collections.get(random().nextInt(collections.size()));
-            futures.add(exec.submit(() -> solrClient.add(col, solrInputDocument, commitWithin)));
-          }
-          for (Future<UpdateResponse> future : futures) {
-            assertUpdateResponse(future.get());
-          }
-          // at this point there shouldn't be any tasks running
-          assertEquals(0, exec.shutdownNow().size());
-        } finally {
-          if (exec != null) {
-            exec.shutdownNow();
-          }
+      CloudSolrClient solrClient = cluster.getSolrClient();
+      try {
+        exec =
+            ExecutorUtil.newMDCAwareFixedThreadPool(
+                1 + random().nextInt(2), new SolrNamedThreadFactory(getSaferTestName()));
+        List<Future<UpdateResponse>> futures = new ArrayList<>(solrInputDocuments.length);
+        for (SolrInputDocument solrInputDocument : solrInputDocuments) {
+          String col = collections.get(random().nextInt(collections.size()));
+          futures.add(exec.submit(() -> solrClient.add(col, solrInputDocument, commitWithin)));
+        }
+        for (Future<UpdateResponse> future : futures) {
+          assertUpdateResponse(future.get());
+        }
+        // at this point there shouldn't be any tasks running
+        assertEquals(0, exec.shutdownNow().size());
+      } finally {
+        if (exec != null) {
+          exec.shutdownNow();
         }
       }
+
     } else {
       // send in a batch.
       String col = collections.get(random().nextInt(collections.size()));
-      try (CloudSolrClient solrClient = getCloudSolrClient(cluster)) {
-        assertUpdateResponse(solrClient.add(col, Arrays.asList(solrInputDocuments), commitWithin));
-      }
+      CloudSolrClient solrClient = cluster.getSolrClient();
+      assertUpdateResponse(solrClient.add(col, Arrays.asList(solrInputDocuments), commitWithin));
     }
     String col = collections.get(random().nextInt(collections.size()));
     if (commitWithin == -1) {
diff --git a/solr/core/src/test/org/apache/solr/update/processor/TimeRoutedAliasUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/update/processor/TimeRoutedAliasUpdateProcessorTest.java
index 32fb14dbf20..9a781215b8e 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/TimeRoutedAliasUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/TimeRoutedAliasUpdateProcessorTest.java
@@ -67,7 +67,6 @@ import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.data.Stat;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -90,7 +89,7 @@ public class TimeRoutedAliasUpdateProcessorTest extends RoutedAliasUpdateProcess
   @Before
   public void doBefore() throws Exception {
     configureCluster(4).configure();
-    solrClient = getCloudSolrClient(cluster);
+    solrClient = cluster.getSolrClient();
     // log this to help debug potential causes of problems
     if (log.isInfoEnabled()) {
       log.info("SolrClient: {}", solrClient);
@@ -98,14 +97,6 @@ public class TimeRoutedAliasUpdateProcessorTest extends RoutedAliasUpdateProcess
     }
   }
 
-  @After
-  public void doAfter() throws Exception {
-    if (null != solrClient) {
-      solrClient.close();
-    }
-    shutdownCluster();
-  }
-
   @Test
   @LogLevel("org.apache.solr.update.processor.TimeRoutedAlias=DEBUG;org.apache.solr.cloud=DEBUG")
   public void test() throws Exception {
diff --git a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
index d27e4c79d12..65ddfefa556 100644
--- a/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
+++ b/solr/modules/hdfs/src/test/org/apache/solr/hdfs/cloud/StressHdfsTest.java
@@ -37,6 +37,7 @@ import org.apache.solr.SolrIgnoredThreadsFilter;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.cloud.AbstractBasicDistributedZkTestBase;
 import org.apache.solr.common.cloud.ClusterState;
@@ -188,7 +189,9 @@ public class StressHdfsTest extends AbstractBasicDistributedZkTestBase {
     int i = 0;
     for (SolrClient client : clients) {
       try (SolrClient c =
-          getHttpSolrClient(getBaseUrl(client) + "/" + DELETE_DATA_DIR_COLLECTION, 30000)) {
+          new HttpSolrClient.Builder(getBaseUrl(client) + "/" + DELETE_DATA_DIR_COLLECTION)
+              .withConnectionTimeout(30000, TimeUnit.MILLISECONDS)
+              .build()) {
         int docCnt = random().nextInt(1000) + 1;
         for (int j = 0; j < docCnt; j++) {
           c.add(getDoc("id", i++, "txt_t", "just some random text for a doc"));
diff --git a/solr/solrj-zookeeper/src/test/org/apache/solr/common/cloud/SolrZkClientTest.java b/solr/solrj-zookeeper/src/test/org/apache/solr/common/cloud/SolrZkClientTest.java
index 60a60dc4e0f..aee07343b97 100644
--- a/solr/solrj-zookeeper/src/test/org/apache/solr/common/cloud/SolrZkClientTest.java
+++ b/solr/solrj-zookeeper/src/test/org/apache/solr/common/cloud/SolrZkClientTest.java
@@ -24,6 +24,7 @@ import java.security.NoSuchAlgorithmException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -63,7 +64,10 @@ public class SolrZkClientTest extends SolrCloudTestCase {
     configureCluster(1)
         .addConfig("_default", new File(ExternalPaths.DEFAULT_CONFIGSET).toPath())
         .configure();
-    solrClient = getCloudSolrClient(cluster.getZkServer().getZkAddress());
+    solrClient =
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
+            .build();
 
     final String SCHEME = "digest";
     final String AUTH = "user:pass";
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
index 27452186ccb..13c279a62dd 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
@@ -16,12 +16,12 @@
  */
 package org.apache.solr.client.solrj;
 
-import static org.apache.solr.SolrTestCaseJ4.getHttpSolrClient;
-
+import java.util.concurrent.TimeUnit;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.solr.SolrTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.junit.Test;
 
 /**
@@ -41,7 +41,10 @@ public class SolrExceptionTest extends SolrTestCase {
       // set a 1ms timeout to let the connection fail faster.
       httpClient = HttpClientUtil.createClient(null);
       try (SolrClient client =
-          getHttpSolrClient("http://" + SolrTestCaseJ4.DEAD_HOST_1 + "/solr/", httpClient, 1)) {
+          new HttpSolrClient.Builder("http://" + SolrTestCaseJ4.DEAD_HOST_1 + "/solr/")
+              .withHttpClient(httpClient)
+              .withConnectionTimeout(1, TimeUnit.MILLISECONDS)
+              .build()) {
         SolrQuery query = new SolrQuery("test123");
         client.query(query);
       }
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java b/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
index 67cb3867043..c251afdba91 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
@@ -31,6 +31,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.client.solrj.response.SolrResponseBase;
@@ -99,7 +100,8 @@ public class TestLBHttpSolrClient extends SolrTestCaseJ4 {
       docs.add(doc);
     }
     SolrResponseBase resp;
-    try (SolrClient client = getHttpSolrClient(solrInstance.getUrl(), httpClient)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(solrInstance.getUrl()).withHttpClient(httpClient).build()) {
       resp = client.add(docs);
       assertEquals(0, resp.getStatus());
       resp = client.commit();
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
index d5e26aeb71c..310054881c1 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
@@ -35,6 +35,7 @@ import org.apache.solr.client.solrj.SolrExampleTests;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrInputDocument;
@@ -60,7 +61,7 @@ public class SolrExampleJettyTest extends SolrExampleTests {
   public void testBadSetup() {
     String url = "http" + (isSSLMode() ? "s" : "") + "://127.0.0.1/?core=xxx";
     // This test does NOT fail for Http2SolrClient
-    expectThrows(Exception.class, () -> getHttp1SolrClient(url));
+    expectThrows(Exception.class, () -> new HttpSolrClient.Builder(url).build());
   }
 
   @Test
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
index 0d5c4441ecb..e153e29598f 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
@@ -29,6 +29,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -208,8 +209,10 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   public void testTimeout() throws Exception {
     SolrQuery q = new SolrQuery("*:*");
     try (SolrClient client =
-        getHttpSolrClient(
-            jetty.getBaseUrl().toString() + "/slow/foo", DEFAULT_CONNECTION_TIMEOUT, 2000)) {
+        new HttpSolrClient.Builder(jetty.getBaseUrl().toString() + "/slow/foo")
+            .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(2000, TimeUnit.MILLISECONDS)
+            .build()) {
       SolrServerException e =
           expectThrows(SolrServerException.class, () -> client.query(q, METHOD.GET));
       assertTrue(e.getMessage().contains("Timeout"));
@@ -575,7 +578,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
       assertNull(DebugServlet.headers.toString(), DebugServlet.headers.get("Accept-Encoding"));
     }
 
-    try (SolrClient client = getHttpSolrClient(clientUrl, null, null, true)) {
+    try (SolrClient client = new HttpSolrClient.Builder(clientUrl).allowCompression(true).build()) {
       try {
         client.query(q);
       } catch (BaseHttpSolrClient.RemoteSolrException ignored) {
@@ -583,7 +586,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
       assertNotNull(DebugServlet.headers.get("Accept-Encoding"));
     }
 
-    try (SolrClient client = getHttpSolrClient(clientUrl, null, null, false)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(clientUrl).allowCompression(false).build()) {
       try {
         client.query(q);
       } catch (BaseHttpSolrClient.RemoteSolrException ignored) {
@@ -648,7 +652,10 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   public void testGetRawStream() throws SolrServerException, IOException {
     CloseableHttpClient client = HttpClientUtil.createClient(null);
     try (SolrClient solrClient =
-        getHttpSolrClient(jetty.getBaseUrl().toString() + "/collection1", client, null); ) {
+        new HttpSolrClient.Builder(jetty.getBaseUrl().toString() + "/collection1")
+            .withHttpClient(client)
+            .withResponseParser(null)
+            .build(); ) {
 
       QueryRequest req = new QueryRequest();
       NamedList<?> response = solrClient.request(req);
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java
index 2b71bbf250c..5f2fc5ee67a 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java
@@ -37,7 +37,7 @@ public class CloudHttp2SolrClientBadInputTest extends SolrCloudTestCase {
 
   @Test
   public void testDeleteByIdReportsInvalidIdLists() throws Exception {
-    try (SolrClient client = getCloudHttp2SolrClient(cluster)) {
+    try (SolrClient client = new RandomizingCloudHttp2SolrClientBuilder(cluster).build()) {
       assertExceptionThrownWithMessageContaining(
           IllegalArgumentException.class,
           List.of("ids", "null"),
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
index 4b2afacffd4..bce1d5fc332 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
@@ -33,6 +33,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.tests.util.TestUtil;
@@ -591,7 +592,11 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
       throws SolrServerException, IOException {
 
     NamedList<Object> resp;
-    try (SolrClient client = getHttpSolrClient(baseUrl + "/" + collectionName, 15000, 60000)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(baseUrl + "/" + collectionName)
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+            .build()) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("qt", "/admin/mbeans");
       params.set("stats", "true");
@@ -820,7 +825,10 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
 
   @Test
   public void testShutdown() throws IOException {
-    try (CloudSolrClient client = getCloudSolrClient(DEAD_HOST_1)) {
+    try (CloudSolrClient client =
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(DEAD_HOST_1), Optional.empty())
+            .build()) {
       try (ZkClientClusterStateProvider zkClientClusterStateProvider =
           ZkClientClusterStateProvider.from(client)) {
         zkClientClusterStateProvider.setZkConnectTimeout(100);
@@ -833,7 +841,10 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
   @Test
   public void testWrongZkChrootTest() throws IOException {
     try (CloudSolrClient client =
-        getCloudSolrClient(cluster.getZkServer().getZkAddress() + "/xyz/foo")) {
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(cluster.getZkServer().getZkAddress() + "/xyz/foo"),
+                Optional.empty())
+            .build()) {
       try (ZkClientClusterStateProvider zkClientClusterStateProvider =
           ZkClientClusterStateProvider.from(client)) {
         zkClientClusterStateProvider.setZkClientTimeout(1000 * 60);
@@ -850,7 +861,10 @@ public class CloudHttp2SolrClientTest extends SolrCloudTestCase {
   public void customHttpClientTest() throws IOException {
     CloseableHttpClient client = HttpClientUtil.createClient(null);
     try (CloudSolrClient solrClient =
-        getCloudSolrClient(cluster.getZkServer().getZkAddress(), client)) {
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
+            .withHttpClient(client)
+            .build()) {
 
       assertSame(((CloudLegacySolrClient) solrClient).getLbClient().getHttpClient(), client);
 
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBadInputTest.java
index e6ba1b863ac..82614a98398 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBadInputTest.java
@@ -37,31 +37,30 @@ public class CloudSolrClientBadInputTest extends SolrCloudTestCase {
 
   @Test
   public void testDeleteByIdReportsInvalidIdLists() throws Exception {
-    try (SolrClient client = getCloudSolrClient(cluster)) {
-      assertExceptionThrownWithMessageContaining(
-          IllegalArgumentException.class,
-          List.of("ids", "null"),
-          () -> {
-            client.deleteById(ANY_COLLECTION, NULL_STR_LIST);
-          });
-      assertExceptionThrownWithMessageContaining(
-          IllegalArgumentException.class,
-          List.of("ids", "empty"),
-          () -> {
-            client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST);
-          });
-      assertExceptionThrownWithMessageContaining(
-          IllegalArgumentException.class,
-          List.of("ids", "null"),
-          () -> {
-            client.deleteById(ANY_COLLECTION, NULL_STR_LIST, ANY_COMMIT_WITHIN_TIME);
-          });
-      assertExceptionThrownWithMessageContaining(
-          IllegalArgumentException.class,
-          List.of("ids", "empty"),
-          () -> {
-            client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST, ANY_COMMIT_WITHIN_TIME);
-          });
-    }
+    SolrClient client = cluster.getSolrClient();
+    assertExceptionThrownWithMessageContaining(
+        IllegalArgumentException.class,
+        List.of("ids", "null"),
+        () -> {
+          client.deleteById(ANY_COLLECTION, NULL_STR_LIST);
+        });
+    assertExceptionThrownWithMessageContaining(
+        IllegalArgumentException.class,
+        List.of("ids", "empty"),
+        () -> {
+          client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST);
+        });
+    assertExceptionThrownWithMessageContaining(
+        IllegalArgumentException.class,
+        List.of("ids", "null"),
+        () -> {
+          client.deleteById(ANY_COLLECTION, NULL_STR_LIST, ANY_COMMIT_WITHIN_TIME);
+        });
+    assertExceptionThrownWithMessageContaining(
+        IllegalArgumentException.class,
+        List.of("ids", "empty"),
+        () -> {
+          client.deleteById(ANY_COLLECTION, EMPTY_STR_LIST, ANY_COMMIT_WITHIN_TIME);
+        });
   }
 }
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
index bccfde52bc3..4ddeb81059b 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
@@ -33,6 +33,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.tests.util.TestUtil;
@@ -592,7 +593,11 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
       throws SolrServerException, IOException {
 
     NamedList<Object> resp;
-    try (SolrClient client = getHttpSolrClient(baseUrl + "/" + collectionName, 15000, 60000)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(baseUrl + "/" + collectionName)
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+            .build()) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("qt", "/admin/mbeans");
       params.set("stats", "true");
@@ -826,7 +831,10 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
 
   @Test
   public void testShutdown() throws IOException {
-    try (CloudSolrClient client = getCloudSolrClient(DEAD_HOST_1)) {
+    try (CloudSolrClient client =
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(DEAD_HOST_1), Optional.empty())
+            .build()) {
       try (ZkClientClusterStateProvider zkClientClusterStateProvider =
           ZkClientClusterStateProvider.from(client)) {
         zkClientClusterStateProvider.setZkConnectTimeout(100);
@@ -839,7 +847,10 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
   @Test
   public void testWrongZkChrootTest() throws IOException {
     try (CloudSolrClient client =
-        getCloudSolrClient(cluster.getZkServer().getZkAddress() + "/xyz/foo")) {
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(cluster.getZkServer().getZkAddress() + "/xyz/foo"),
+                Optional.empty())
+            .build()) {
       try (ZkClientClusterStateProvider zkClientClusterStateProvider =
           ZkClientClusterStateProvider.from(client)) {
         zkClientClusterStateProvider.setZkConnectTimeout(1000 * 60);
@@ -861,7 +872,10 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
   public void customHttpClientTest() throws IOException {
     CloseableHttpClient client = HttpClientUtil.createClient(null);
     try (CloudSolrClient solrClient =
-        getCloudSolrClient(cluster.getZkServer().getZkAddress(), client)) {
+        new RandomizingCloudSolrClientBuilder(
+                Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
+            .withHttpClient(client)
+            .build()) {
 
       assertSame(((CloudLegacySolrClient) solrClient).getLbClient().getHttpClient(), client);
 
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
index 45f438ab4bf..371ea543e99 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBadInputTest.java
@@ -43,10 +43,10 @@ public class ConcurrentUpdateSolrClientBadInputTest extends SolrJettyTestBase {
   @Test
   public void testDeleteByIdReportsInvalidIdLists() throws Exception {
     try (SolrClient client =
-        getConcurrentUpdateSolrClient(
-            jetty.getBaseUrl().toString() + "/" + ANY_COLLECTION,
-            ANY_QUEUE_SIZE,
-            ANY_MAX_NUM_THREADS)) {
+        new ConcurrentUpdateSolrClient.Builder(jetty.getBaseUrl().toString() + "/" + ANY_COLLECTION)
+            .withQueueSize(ANY_QUEUE_SIZE)
+            .withThreadCount(ANY_MAX_NUM_THREADS)
+            .build()) {
       assertExceptionThrownWithMessageContaining(
           IllegalArgumentException.class,
           List.of("ids", "null"),
@@ -74,8 +74,10 @@ public class ConcurrentUpdateSolrClientBadInputTest extends SolrJettyTestBase {
     }
 
     try (SolrClient client =
-        getConcurrentUpdateSolrClient(
-            jetty.getBaseUrl().toString(), ANY_QUEUE_SIZE, ANY_MAX_NUM_THREADS)) {
+        new ConcurrentUpdateSolrClient.Builder(jetty.getBaseUrl().toString())
+            .withQueueSize(ANY_QUEUE_SIZE)
+            .withThreadCount(ANY_MAX_NUM_THREADS)
+            .build()) {
       assertExceptionThrownWithMessageContaining(
           IllegalArgumentException.class,
           List.of("ids", "null"),
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
index e706f25908d..893ae51cdc0 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
@@ -254,7 +254,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
         SolrException.ErrorCode.getErrorCode(status));
 
     try (Http2SolrClient client =
-        getHttp2SolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+        new Http2SolrClient.Builder(jetty.getBaseUrl().toString() + "/debug/foo").build()) {
       DebugServlet.setErrorCode(status);
       try {
         SolrQuery q = new SolrQuery("foo");
@@ -281,7 +281,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
         SolrException.ErrorCode.UNKNOWN,
         SolrException.ErrorCode.getErrorCode(status));
 
-    try (Http2SolrClient client = getHttp2SolrClient(null)) {
+    try (Http2SolrClient client = new Http2SolrClient.Builder(null).build()) {
       DebugServlet.setErrorCode(status);
       try {
         // if client base url is null, request url will be used in exception message
@@ -305,7 +305,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
     String url = jetty.getBaseUrl().toString() + "/debug/foo";
     SolrQuery q = new SolrQuery("foo");
     q.setParam("a", "\u1234");
-    try (Http2SolrClient client = getHttp2SolrClient(url)) {
+    try (Http2SolrClient client = new Http2SolrClient.Builder(url).build()) {
 
       try {
         client.query(q, SolrRequest.METHOD.GET);
@@ -433,7 +433,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
   public void testDelete() throws Exception {
     DebugServlet.clear();
     String url = jetty.getBaseUrl().toString() + "/debug/foo";
-    try (Http2SolrClient client = getHttp2SolrClient(url)) {
+    try (Http2SolrClient client = new Http2SolrClient.Builder(url).build()) {
       try {
         client.deleteById("id");
       } catch (BaseHttpSolrClient.RemoteSolrException ignored) {
@@ -477,7 +477,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
   public void testGetById() throws Exception {
     DebugServlet.clear();
     try (Http2SolrClient client =
-        getHttp2SolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+        new Http2SolrClient.Builder(jetty.getBaseUrl().toString() + "/debug/foo").build()) {
       Collection<String> ids = Collections.singletonList("a");
       try {
         client.getById("a");
@@ -508,7 +508,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
     UpdateRequest req = new UpdateRequest();
     req.add(new SolrInputDocument());
     req.setParam("a", "\u1234");
-    try (Http2SolrClient client = getHttp2SolrClient(url)) {
+    try (Http2SolrClient client = new Http2SolrClient.Builder(url).build()) {
 
       try {
         client.request(req);
@@ -634,7 +634,8 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
   @Test
   public void testCollectionParameters() throws IOException, SolrServerException {
 
-    try (Http2SolrClient client = getHttp2SolrClient(jetty.getBaseUrl().toString())) {
+    try (Http2SolrClient client =
+        new Http2SolrClient.Builder(jetty.getBaseUrl().toString()).build()) {
       SolrInputDocument doc = new SolrInputDocument();
       doc.addField("id", "collection");
       client.add("collection1", doc);
@@ -646,7 +647,7 @@ public class Http2SolrClientTest extends SolrJettyTestBase {
     }
 
     final String collection1Url = jetty.getBaseUrl().toString() + "/collection1";
-    try (Http2SolrClient client = getHttp2SolrClient(collection1Url)) {
+    try (Http2SolrClient client = new Http2SolrClient.Builder(collection1Url).build()) {
       assertEquals(1, client.query(new SolrQuery("id:collection")).getResults().getNumFound());
     }
   }
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
index 0d32f168315..d030b3e98b7 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java
@@ -41,7 +41,9 @@ public class LBHttpSolrClientBadInputTest extends SolrJettyTestBase {
   @Test
   public void testDeleteByIdReportsInvalidIdLists() throws Exception {
     try (SolrClient client =
-        getLBHttpSolrClient(jetty.getBaseUrl().toString() + "/" + ANY_COLLECTION)) {
+        new LBHttpSolrClient.Builder()
+            .withBaseSolrUrls(jetty.getBaseUrl().toString() + "/" + ANY_COLLECTION)
+            .build()) {
       assertExceptionThrownWithMessageContaining(
           IllegalArgumentException.class,
           List.of("ids", "null"),
@@ -68,7 +70,8 @@ public class LBHttpSolrClientBadInputTest extends SolrJettyTestBase {
           });
     }
 
-    try (SolrClient client = getLBHttpSolrClient(jetty.getBaseUrl().toString())) {
+    try (SolrClient client =
+        new LBHttpSolrClient.Builder().withBaseSolrUrls(jetty.getBaseUrl().toString()).build()) {
       assertExceptionThrownWithMessageContaining(
           IllegalArgumentException.class,
           List.of("ids", "null"),
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java b/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
index 3b7c5ac32a4..3f946add592 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
@@ -160,7 +160,7 @@ public abstract class SolrJettyTestBase extends SolrTestCaseJ4 {
    * options.
    */
   public SolrClient createNewSolrClient() {
-    return getHttpSolrClient(getServerUrl());
+    return new HttpSolrClient.Builder(getServerUrl()).build();
   }
 
   public HttpClient getHttpClient() {
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 9eb0d1b9a9e..7438fcbe69a 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -46,7 +46,6 @@ import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
@@ -89,17 +88,12 @@ import org.apache.lucene.tests.analysis.MockTokenizer;
 import org.apache.lucene.tests.util.LuceneTestCase.SuppressFileSystems;
 import org.apache.lucene.tests.util.TestUtil;
 import org.apache.lucene.util.Constants;
-import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.impl.CloudHttp2SolrClient;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
-import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.ClusterStateProvider;
-import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient;
 import org.apache.solr.client.solrj.impl.Http2SolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
-import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
-import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
 import org.apache.solr.client.solrj.response.SolrResponseBase;
 import org.apache.solr.client.solrj.util.ClientUtils;
 import org.apache.solr.cloud.IpTables;
@@ -2590,15 +2584,6 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
     }
   }
 
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.CloudHttp2SolrClient.Builder} class directly
-   */
-  public static CloudHttp2SolrClient getCloudHttp2SolrClient(MiniSolrCloudCluster cluster) {
-    return new RandomizingCloudHttp2SolrClientBuilder(cluster).build();
-  }
-
   /**
    * A variant of {@link org.apache.solr.client.solrj.impl.CloudLegacySolrClient.Builder} that will
    * randomize some internal settings.
@@ -2644,145 +2629,6 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
     }
   }
 
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
-   */
-  public static CloudSolrClient getCloudSolrClient(String zkHost) {
-    return new RandomizingCloudSolrClientBuilder(
-            Collections.singletonList(zkHost), Optional.empty())
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
-   */
-  public static CloudSolrClient getCloudSolrClient(MiniSolrCloudCluster cluster) {
-    return new RandomizingCloudSolrClientBuilder(cluster).build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
-   */
-  public static CloudSolrClient getCloudSolrClient(String zkHost, HttpClient httpClient) {
-    return new RandomizingCloudSolrClientBuilder(
-            Collections.singletonList(zkHost), Optional.empty())
-        .withHttpClient(httpClient)
-        .build();
-  }
-
-  public static RandomizingCloudSolrClientBuilder newCloudSolrClient(String zkHost) {
-    return new RandomizingCloudSolrClientBuilder(
-        Collections.singletonList(zkHost), Optional.empty());
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
-   */
-  public static CloudSolrClient getCloudSolrClient(
-      String zkHost,
-      String defaultCollection,
-      boolean shardLeadersOnly,
-      int connectionTimeoutMillis,
-      int socketTimeoutMillis) {
-    RandomizingCloudSolrClientBuilder builder =
-        new RandomizingCloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty());
-    if (shardLeadersOnly) {
-      builder.sendUpdatesOnlyToShardLeaders();
-    } else {
-      builder.sendUpdatesToAllReplicasInShard();
-    }
-    if (defaultCollection != null) {
-      builder.withDefaultCollection(defaultCollection);
-    }
-    return builder
-        .withConnectionTimeout(connectionTimeoutMillis)
-        .withSocketTimeout(socketTimeoutMillis)
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
-   */
-  public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(
-      String baseSolrUrl, int queueSize, int threadCount) {
-    return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
-        .withQueueSize(queueSize)
-        .withThreadCount(threadCount)
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
-   */
-  public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(
-      String baseSolrUrl, int queueSize, int threadCount, int connectionTimeoutMillis) {
-    return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
-        .withQueueSize(queueSize)
-        .withThreadCount(threadCount)
-        .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
-   */
-  public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(
-      String baseSolrUrl, HttpClient httpClient, int queueSize, int threadCount) {
-    return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
-        .withHttpClient(httpClient)
-        .withQueueSize(queueSize)
-        .withThreadCount(threadCount)
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
-   */
-  public static LBHttpSolrClient getLBHttpSolrClient(HttpClient client, String... solrUrls) {
-    return new LBHttpSolrClient.Builder().withHttpClient(client).withBaseSolrUrls(solrUrls).build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
-   */
-  public static LBHttpSolrClient getLBHttpSolrClient(
-      HttpClient client, int connectionTimeoutMillis, int socketTimeoutMillis, String... solrUrls) {
-    return new LBHttpSolrClient.Builder()
-        .withHttpClient(client)
-        .withBaseSolrUrls(solrUrls)
-        .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
-        .withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS)
-        .build();
-  }
-
-  /**
-   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
-   * not wish to have any randomized behavior should use the {@link
-   * org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
-   */
-  public static LBHttpSolrClient getLBHttpSolrClient(String... solrUrls)
-      throws MalformedURLException {
-    return new LBHttpSolrClient.Builder().withBaseSolrUrls(solrUrls).build();
-  }
-
   /** This method creates a HttpClient from a URL. */
   @Deprecated // We are migrating away from Apache HttpClient.
   public static HttpClient getHttpClient(String url) {
@@ -2791,92 +2637,12 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
 
   /**
    * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttp1SolrClient(String url) {
-    return new HttpSolrClient.Builder(url).build();
-  }
-
-  /**
-   * This method creates a basic Http2SolrClient. Tests that want to control the creation process
    * should use the {@link org.apache.solr.client.solrj.impl.Http2SolrClient.Builder} class directly
    */
-  public static Http2SolrClient getHttp2SolrClient(String url) {
-    return new Http2SolrClient.Builder(url).build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(
-      String url, HttpClient httpClient, ResponseParser responseParser, boolean compression) {
-    return new Builder(url)
-        .withHttpClient(httpClient)
-        .withResponseParser(responseParser)
-        .allowCompression(compression)
-        .build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(
-      String url, HttpClient httpClient, ResponseParser responseParser) {
-    return new Builder(url).withHttpClient(httpClient).withResponseParser(responseParser).build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient) {
-    return new Builder(url).withHttpClient(httpClient).build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(
-      String url, HttpClient httpClient, int connectionTimeoutMillis) {
-    return new Builder(url)
-        .withHttpClient(httpClient)
-        .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
-        .build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
   public static HttpSolrClient getHttpSolrClient(String url) {
     return new HttpSolrClient.Builder(url).build();
   }
 
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(String url, int connectionTimeoutMillis) {
-    return new Builder(url)
-        .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
-        .build();
-  }
-
-  /**
-   * This method creates a basic HttpSolrClient. Tests that want to control the creation process
-   * should use the {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
-   */
-  public static HttpSolrClient getHttpSolrClient(
-      String url, int connectionTimeoutMillis, int socketTimeoutMillis) {
-    return new Builder(url)
-        .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
-        .withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS)
-        .build();
-  }
-
   /**
    * Returns a randomly generated Date in the appropriate Solr external (input) format
    *
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
index 6e5d086f84f..edcd0a562fd 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
@@ -1300,7 +1300,11 @@ public abstract class AbstractBasicDistributedZkTestBase extends AbstractFullDis
     String collection = elements[elements.length - 1];
     String urlString = url.toString();
     urlString = urlString.substring(0, urlString.length() - collection.length() - 1);
-    try (SolrClient client = getHttpSolrClient(urlString, 15000, 60000)) {
+    try (SolrClient client =
+        new HttpSolrClient.Builder(urlString)
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+            .build()) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       // params.set("qt", "/admin/metrics?prefix=UPDATE.updateHandler&registry=solr.core." +
       // collection);
@@ -1398,7 +1402,10 @@ public abstract class AbstractBasicDistributedZkTestBase extends AbstractFullDis
 
     // now test that unloading a core gets us a new leader
     try (SolrClient unloadClient =
-        getHttpSolrClient(jettys.get(0).getBaseUrl().toString(), 15000, 60000)) {
+        new HttpSolrClient.Builder(jettys.get(0).getBaseUrl().toString())
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+            .build()) {
       Unload unloadCmd = new Unload(true);
       unloadCmd.setCoreName(props.getCoreName());
 
@@ -1715,7 +1722,10 @@ public abstract class AbstractBasicDistributedZkTestBase extends AbstractFullDis
       String collection, String baseUrl, int connectionTimeoutMillis, int socketTimeoutMillis) {
 
     SolrClient client =
-        getHttpSolrClient(baseUrl + "/" + collection, connectionTimeoutMillis, socketTimeoutMillis);
+        new HttpSolrClient.Builder(baseUrl + "/" + collection)
+            .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS)
+            .build();
 
     return client;
   }
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
index 0b3948d4fd6..b21aa73831a 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
@@ -35,6 +35,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Random;
 import java.util.Set;
@@ -2172,6 +2173,33 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
         configName);
   }
 
+  /**
+   * This method <i>may</i> randomize unspecified aspects of the resulting SolrClient. Tests that do
+   * not wish to have any randomized behavior should use the {@link
+   * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
+   */
+  public static CloudSolrClient getCloudSolrClient(
+      String zkHost,
+      String defaultCollection,
+      boolean shardLeadersOnly,
+      int connectionTimeoutMillis,
+      int socketTimeoutMillis) {
+    RandomizingCloudSolrClientBuilder builder =
+        new RandomizingCloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty());
+    if (shardLeadersOnly) {
+      builder.sendUpdatesOnlyToShardLeaders();
+    } else {
+      builder.sendUpdatesToAllReplicasInShard();
+    }
+    if (defaultCollection != null) {
+      builder.withDefaultCollection(defaultCollection);
+    }
+    return builder
+        .withConnectionTimeout(connectionTimeoutMillis)
+        .withSocketTimeout(socketTimeoutMillis)
+        .build();
+  }
+
   @Override
   protected SolrClient createNewSolrClient(int port) {
     return createNewSolrClient(DEFAULT_COLLECTION, port);
@@ -2180,7 +2208,10 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
   protected SolrClient createNewSolrClient(String coreName, int port) {
     String baseUrl = buildUrl(port);
     String url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + coreName;
-    return getHttpSolrClient(url, DEFAULT_CONNECTION_TIMEOUT, 60000);
+    return new HttpSolrClient.Builder(url)
+        .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
+        .withSocketTimeout(60000, TimeUnit.MILLISECONDS)
+        .build();
   }
 
   protected SolrClient createNewSolrClient(String collection, String baseUrl) {
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractSyncSliceTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractSyncSliceTestBase.java
index 6b177d3dc5e..26690d699d8 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractSyncSliceTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractSyncSliceTestBase.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.common.SolrInputDocument;
@@ -104,7 +105,10 @@ public abstract class AbstractSyncSliceTestBase extends AbstractFullDistribZkTes
     String baseUrl = shardToJetty.get(SHARD1).get(2).jetty.getBaseUrl().toString();
 
     // we only set the connect timeout, not so timeout
-    try (SolrClient baseClient = getHttpSolrClient(baseUrl, 30000)) {
+    try (SolrClient baseClient =
+        new HttpSolrClient.Builder(baseUrl)
+            .withConnectionTimeout(30000, TimeUnit.MILLISECONDS)
+            .build()) {
       baseClient.request(request);
     }
 
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
index 1a23f3373be..423a02d6f8f 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractUnloadDistributedZkTestBase.java
@@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.Unload;
 import org.apache.solr.common.SolrInputDocument;
@@ -83,6 +84,13 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     testUnloadShardAndCollection();
   }
 
+  private SolrClient newSolrClient(String url) {
+    return new HttpSolrClient.Builder(url)
+        .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+        .withSocketTimeout(30000, TimeUnit.MILLISECONDS)
+        .build();
+  }
+
   private void checkCoreNamePresenceAndSliceCount(
       String collectionName, String coreName, boolean shouldBePresent, int expectedSliceCount)
       throws Exception {
@@ -271,8 +279,9 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     TestInjection.skipIndexWriterCommitOnClose = true;
 
     try (SolrClient addClient =
-        getHttpSolrClient(
-            jettys.get(2).getBaseUrl() + "/unloadcollection_shard1_replica3", 30000)) {
+        new HttpSolrClient.Builder(jettys.get(2).getBaseUrl() + "/unloadcollection_shard1_replica3")
+            .withConnectionTimeout(30000, TimeUnit.MILLISECONDS)
+            .build()) {
 
       // add a few docs
       for (int x = 20; x < 100; x++) {
@@ -285,7 +294,7 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     // collectionClient.commit();
 
     // unload the leader
-    try (SolrClient collectionClient = getHttpSolrClient(leaderProps.getBaseUrl(), 15000, 30000)) {
+    try (SolrClient collectionClient = newSolrClient(leaderProps.getBaseUrl())) {
 
       Unload unloadCmd = new Unload(false);
       unloadCmd.setCoreName(leaderProps.getCoreName());
@@ -310,8 +319,10 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     zkStateReader.getLeaderRetry("unloadcollection", "shard1", 15000);
 
     try (SolrClient addClient =
-        getHttpSolrClient(
-            jettys.get(1).getBaseUrl() + "/unloadcollection_shard1_replica2", 30000, 90000)) {
+        new HttpSolrClient.Builder(jettys.get(1).getBaseUrl() + "/unloadcollection_shard1_replica2")
+            .withConnectionTimeout(30000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(90000, TimeUnit.MILLISECONDS)
+            .build()) {
 
       // add a few docs while the leader is down
       for (int x = 101; x < 200; x++) {
@@ -332,7 +343,7 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
 
     // unload the leader again
     leaderProps = getLeaderUrlFromZk("unloadcollection", "shard1");
-    try (SolrClient collectionClient = getHttpSolrClient(leaderProps.getBaseUrl(), 15000, 30000)) {
+    try (SolrClient collectionClient = newSolrClient(leaderProps.getBaseUrl())) {
 
       Unload unloadCmd = new Unload(false);
       unloadCmd.setCoreName(leaderProps.getCoreName());
@@ -364,8 +375,7 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     long found1, found3;
 
     try (SolrClient adminClient =
-        getHttpSolrClient(
-            jettys.get(1).getBaseUrl() + "/unloadcollection_shard1_replica2", 15000, 30000)) {
+        newSolrClient((jettys.get(1).getBaseUrl() + "/unloadcollection_shard1_replica2"))) {
       adminClient.commit();
       SolrQuery q = new SolrQuery("*:*");
       q.set("distrib", false);
@@ -373,8 +383,10 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     }
 
     try (SolrClient adminClient =
-        getHttpSolrClient(
-            jettys.get(2).getBaseUrl() + "/unloadcollection_shard1_replica3", 15000, 30000)) {
+        new HttpSolrClient.Builder(jettys.get(2).getBaseUrl() + "/unloadcollection_shard1_replica3")
+            .withConnectionTimeout(15000, TimeUnit.MILLISECONDS)
+            .withSocketTimeout(30000, TimeUnit.MILLISECONDS)
+            .build()) {
       adminClient.commit();
       SolrQuery q = new SolrQuery("*:*");
       q.set("distrib", false);
@@ -382,8 +394,7 @@ public abstract class AbstractUnloadDistributedZkTestBase extends AbstractFullDi
     }
 
     try (SolrClient adminClient =
-        getHttpSolrClient(
-            jettys.get(3).getBaseUrl() + "/unloadcollection_shard1_replica4", 15000, 30000)) {
+        newSolrClient((jettys.get(3).getBaseUrl() + "/unloadcollection_shard1_replica4"))) {
       adminClient.commit();
       SolrQuery q = new SolrQuery("*:*");
       q.set("distrib", false);
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java
index 9926854bd34..7856a5e3a53 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java
@@ -35,6 +35,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.client.solrj.request.CoreStatus;
 import org.apache.solr.common.cloud.CollectionStatePredicate;
@@ -293,9 +294,9 @@ public class SolrCloudTestCase extends SolrTestCaseJ4 {
       throws IOException, SolrServerException {
     JettySolrRunner jetty = cluster.getReplicaJetty(replica);
     try (SolrClient client =
-        getHttpSolrClient(
-            jetty.getBaseUrl().toString(),
-            ((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient())) {
+        new HttpSolrClient.Builder(jetty.getBaseUrl().toString())
+            .withHttpClient(((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient())
+            .build()) {
       return CoreAdminRequest.getCoreStatus(replica.getCoreName(), client);
     }
   }