You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by eo...@apache.org on 2023/02/15 07:38:55 UTC

[zookeeper] branch branch-3.8 updated: [ZOOKEEPER-4647] Tests don't pass on JDK20 because we try to mock InetAddress (#1959)

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

eolivelli pushed a commit to branch branch-3.8
in repository https://gitbox.apache.org/repos/asf/zookeeper.git


The following commit(s) were added to refs/heads/branch-3.8 by this push:
     new 6e2fd288e [ZOOKEEPER-4647] Tests don't pass on JDK20 because we try to mock InetAddress (#1959)
6e2fd288e is described below

commit 6e2fd288e86178814157539928e87c139350bd85
Author: Enrico Olivelli <eo...@apache.org>
AuthorDate: Wed Feb 15 08:36:39 2023 +0100

    [ZOOKEEPER-4647] Tests don't pass on JDK20 because we try to mock InetAddress (#1959)
    
    - upgrade Mockito to 4.9.0
    - use BurningWave DNS mock tools
    
    (cherry picked from commit 2e9c3f3ceda90aeb9380acc87b253bf7661b7794)
---
 pom.xml                                            |   8 +-
 zookeeper-server/pom.xml                           |   5 +
 .../zookeeper/common/ZKHostnameVerifier.java       |   2 +-
 .../apache/zookeeper/common/ZKTrustManager.java    |  13 +-
 .../zookeeper/common/ZKTrustManagerTest.java       | 132 ++++++++++++++-------
 .../server/quorum/QuorumCanonicalizeTest.java      |  29 ++++-
 .../zookeeper/test/StaticHostProviderTest.java     |  53 +++++----
 7 files changed, 170 insertions(+), 72 deletions(-)

diff --git a/pom.xml b/pom.xml
index d78a59ab5..b779296cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -464,7 +464,7 @@
     <jmockit.version>1.48</jmockit.version>
     <junit.version>5.6.2</junit.version>
     <junit-platform.version>1.6.2</junit-platform.version>
-    <mockito.version>3.6.28</mockito.version>
+    <mockito.version>4.9.0</mockito.version>
     <hamcrest.version>2.2</hamcrest.version>
     <commons-cli.version>1.5.0</commons-cli.version>
     <netty.version>4.1.86.Final</netty.version>
@@ -480,6 +480,7 @@
     <checkstyle.version>8.39</checkstyle.version>
     <enforcer.version>3.0.0-M3</enforcer.version>
     <commons-io.version>2.11.0</commons-io.version>
+    <burningwave.mockdns.version>0.25.4</burningwave.mockdns.version>
 
     <!-- parameters to pass to C client build -->
     <c-client-openssl>yes</c-client-openssl>
@@ -671,6 +672,11 @@
         <artifactId>commons-io</artifactId>
         <version>${commons-io.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.burningwave</groupId>
+        <artifactId>tools</artifactId>
+        <version>${burningwave.mockdns.version}</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
diff --git a/zookeeper-server/pom.xml b/zookeeper-server/pom.xml
index ac4d83cc6..5a96d458f 100755
--- a/zookeeper-server/pom.xml
+++ b/zookeeper-server/pom.xml
@@ -167,6 +167,11 @@
       <artifactId>junit-platform-runner</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.burningwave</groupId>
+      <artifactId>tools</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.xerial.snappy</groupId>
       <artifactId>snappy-java</artifactId>
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java
index db5af19c5..247ae3917 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java
@@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory;
  * Note: copied from Apache httpclient with some modifications. We want host verification, but depending
  * on the httpclient jar caused unexplained performance regressions (even when the code was not used).
  */
-final class ZKHostnameVerifier implements HostnameVerifier {
+class ZKHostnameVerifier implements HostnameVerifier {
 
     /**
      * Note: copied from Apache httpclient with some minor modifications. We want host verification, but depending
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java
index 34bf4dc97..2573e3fce 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java
@@ -58,10 +58,21 @@ public class ZKTrustManager extends X509ExtendedTrustManager {
         X509ExtendedTrustManager x509ExtendedTrustManager,
         boolean serverHostnameVerificationEnabled,
         boolean clientHostnameVerificationEnabled) {
+        this(x509ExtendedTrustManager,
+                serverHostnameVerificationEnabled,
+                clientHostnameVerificationEnabled,
+                new ZKHostnameVerifier());
+    }
+
+    ZKTrustManager(
+            X509ExtendedTrustManager x509ExtendedTrustManager,
+            boolean serverHostnameVerificationEnabled,
+            boolean clientHostnameVerificationEnabled,
+            ZKHostnameVerifier hostnameVerifier) {
         this.x509ExtendedTrustManager = x509ExtendedTrustManager;
         this.serverHostnameVerificationEnabled = serverHostnameVerificationEnabled;
         this.clientHostnameVerificationEnabled = clientHostnameVerificationEnabled;
-        hostnameVerifier = new ZKHostnameVerifier();
+        this.hostnameVerifier = hostnameVerifier;
     }
 
     @Override
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTrustManagerTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTrustManagerTest.java
index c549a9ce9..7b4e8783e 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTrustManagerTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTrustManagerTest.java
@@ -18,6 +18,8 @@
 
 package org.apache.zookeeper.common;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -30,10 +32,16 @@ import java.security.KeyPairGenerator;
 import java.security.Security;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
+import java.util.concurrent.CopyOnWriteArrayList;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
 import javax.net.ssl.X509ExtendedTrustManager;
 import org.apache.zookeeper.ZKTestCase;
 import org.bouncycastle.asn1.x500.X500NameBuilder;
@@ -49,25 +57,46 @@ import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.operator.ContentSigner;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.burningwave.tools.net.DefaultHostResolver;
+import org.burningwave.tools.net.HostResolutionRequestInterceptor;
+import org.burningwave.tools.net.MappedHostResolver;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 // We can only test calls to ZKTrustManager using Sockets (not SSLEngines). This can be fine since the logic is the same.
 public class ZKTrustManagerTest extends ZKTestCase {
 
+    protected static final Logger LOG = LoggerFactory.getLogger(ZKTrustManagerTest.class);
+
     private static KeyPair keyPair;
 
     private X509ExtendedTrustManager mockX509ExtendedTrustManager;
     private static final String IP_ADDRESS = "127.0.0.1";
     private static final String HOSTNAME = "localhost";
-
-    private InetAddress mockInetAddress;
     private Socket mockSocket;
 
+    @BeforeAll
+    public static void setupDNSMocks() {
+        Map<String, String> hostAliases = new LinkedHashMap<>();
+        hostAliases.put(HOSTNAME, IP_ADDRESS);
+
+        HostResolutionRequestInterceptor.INSTANCE.install(
+                new MappedHostResolver(hostAliases),
+                DefaultHostResolver.INSTANCE
+        );
+    }
+
+    @AfterAll
+    public static void clearDNSMocks() {
+        HostResolutionRequestInterceptor.INSTANCE.uninstall();
+    }
+
     @BeforeAll
     public static void createKeyPair() throws Exception {
         Security.addProvider(new BouncyCastleProvider());
@@ -85,20 +114,7 @@ public class ZKTrustManagerTest extends ZKTestCase {
     public void setup() throws Exception {
         mockX509ExtendedTrustManager = mock(X509ExtendedTrustManager.class);
 
-        mockInetAddress = mock(InetAddress.class);
-        when(mockInetAddress.getHostAddress()).thenAnswer(new Answer() {
-            @Override
-            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
-                return IP_ADDRESS;
-            }
-        });
-
-        when(mockInetAddress.getHostName()).thenAnswer(new Answer() {
-            @Override
-            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
-                return HOSTNAME;
-            }
-        });
+        InetAddress mockInetAddress = InetAddress.getByName(HOSTNAME);
 
         mockSocket = mock(Socket.class);
         when(mockSocket.getInetAddress()).thenAnswer(new Answer() {
@@ -143,106 +159,140 @@ public class ZKTrustManagerTest extends ZKTestCase {
 
     @Test
     public void testServerHostnameVerificationWithHostnameVerificationDisabled() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, false);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, false,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(IP_ADDRESS, HOSTNAME);
         zkTrustManager.checkServerTrusted(certificateChain, null, mockSocket);
-
-        verify(mockInetAddress, times(0)).getHostAddress();
-        verify(mockInetAddress, times(0)).getHostName();
+        verify(mockSocket, times(0)).getInetAddress();
+        assertTrue(hostnameVerifier.hosts.isEmpty());
 
         verify(mockX509ExtendedTrustManager, times(1)).checkServerTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testServerHostnameVerificationWithHostnameVerificationDisabledAndClientHostnameVerificationEnabled() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, true);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, true,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(IP_ADDRESS, HOSTNAME);
         zkTrustManager.checkServerTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(0)).getInetAddress();
 
-        verify(mockInetAddress, times(0)).getHostAddress();
-        verify(mockInetAddress, times(0)).getHostName();
+        assertTrue(hostnameVerifier.hosts.isEmpty());
 
         verify(mockX509ExtendedTrustManager, times(1)).checkServerTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testServerHostnameVerificationWithIPAddress() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, false);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, false,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(IP_ADDRESS, null);
         zkTrustManager.checkServerTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(1)).getInetAddress();
 
-        verify(mockInetAddress, times(1)).getHostAddress();
-        verify(mockInetAddress, times(0)).getHostName();
+        assertEquals(Arrays.asList(IP_ADDRESS), hostnameVerifier.hosts);
 
         verify(mockX509ExtendedTrustManager, times(1)).checkServerTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testServerHostnameVerificationWithHostname() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, false);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, false,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(null, HOSTNAME);
         zkTrustManager.checkServerTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(1)).getInetAddress();
 
-        verify(mockInetAddress, times(1)).getHostAddress();
-        verify(mockInetAddress, times(1)).getHostName();
+        assertEquals(Arrays.asList(IP_ADDRESS, HOSTNAME), hostnameVerifier.hosts);
 
         verify(mockX509ExtendedTrustManager, times(1)).checkServerTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testClientHostnameVerificationWithHostnameVerificationDisabled() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, true);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, false, true,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(null, HOSTNAME);
         zkTrustManager.checkClientTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(1)).getInetAddress();
 
-        verify(mockInetAddress, times(1)).getHostAddress();
-        verify(mockInetAddress, times(1)).getHostName();
+        assertEquals(Arrays.asList(IP_ADDRESS, HOSTNAME), hostnameVerifier.hosts);
 
         verify(mockX509ExtendedTrustManager, times(1)).checkClientTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testClientHostnameVerificationWithClientHostnameVerificationDisabled() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, false);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true,
+                false, hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(null, HOSTNAME);
         zkTrustManager.checkClientTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(0)).getInetAddress();
 
-        verify(mockInetAddress, times(0)).getHostAddress();
-        verify(mockInetAddress, times(0)).getHostName();
+        assertTrue(hostnameVerifier.hosts.isEmpty());
 
         verify(mockX509ExtendedTrustManager, times(1)).checkClientTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testClientHostnameVerificationWithIPAddress() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, true);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, true,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(IP_ADDRESS, null);
         zkTrustManager.checkClientTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(1)).getInetAddress();
 
-        verify(mockInetAddress, times(1)).getHostAddress();
-        verify(mockInetAddress, times(0)).getHostName();
+        assertEquals(Arrays.asList(IP_ADDRESS), hostnameVerifier.hosts);
 
         verify(mockX509ExtendedTrustManager, times(1)).checkClientTrusted(certificateChain, null, mockSocket);
     }
 
     @Test
     public void testClientHostnameVerificationWithHostname() throws Exception {
-        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, true);
+        VerifiableHostnameVerifier hostnameVerifier = new VerifiableHostnameVerifier();
+        ZKTrustManager zkTrustManager = new ZKTrustManager(mockX509ExtendedTrustManager, true, true,
+                hostnameVerifier);
 
         X509Certificate[] certificateChain = createSelfSignedCertifcateChain(null, HOSTNAME);
         zkTrustManager.checkClientTrusted(certificateChain, null, mockSocket);
+        verify(mockSocket, times(1)).getInetAddress();
 
-        verify(mockInetAddress, times(1)).getHostAddress();
-        verify(mockInetAddress, times(1)).getHostName();
+        assertEquals(Arrays.asList(IP_ADDRESS, HOSTNAME), hostnameVerifier.hosts);
 
         verify(mockX509ExtendedTrustManager, times(1)).checkClientTrusted(certificateChain, null, mockSocket);
     }
 
+
+    static class VerifiableHostnameVerifier extends ZKHostnameVerifier {
+
+        List<String> hosts = new CopyOnWriteArrayList<>();
+
+        @Override
+        public boolean verify(String host, SSLSession session) {
+            throw new IllegalArgumentException("not expected to be called by these tests");
+        }
+
+        @Override
+        void verify(String host, X509Certificate cert) throws SSLException {
+            LOG.info("verifyWithX509Certificate {} {}", host, cert);
+            hosts.add(host);
+            super.verify(host, cert);
+        }
+    }
+
+
 }
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumCanonicalizeTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumCanonicalizeTest.java
index 07445f325..aec017a08 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumCanonicalizeTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumCanonicalizeTest.java
@@ -19,13 +19,18 @@
 package org.apache.zookeeper.server.quorum;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import org.apache.zookeeper.ZKTestCase;
 import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
+import org.burningwave.tools.net.DefaultHostResolver;
+import org.burningwave.tools.net.HostResolutionRequestInterceptor;
+import org.burningwave.tools.net.MappedHostResolver;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 public class QuorumCanonicalizeTest extends ZKTestCase {
@@ -35,16 +40,28 @@ public class QuorumCanonicalizeTest extends ZKTestCase {
     private static final String ZK1_ALIAS = "zookeeper.invalid";
     private static final String ZK1_FQDN = "zk1.invalid";
     private static final String ZK1_IP = "169.254.0.42";
-    private static final InetAddress IA_MOCK_ZK1;
+    private static InetAddress IA_MOCK_ZK1;
 
-    static {
-        InetAddress ia = mock(InetAddress.class);
+    @BeforeAll
+    public static void setupDNSMocks() throws Exception {
+        Map<String, String> hostAliases = new LinkedHashMap<>();
+        hostAliases.put(ZK1_FQDN, ZK1_IP);
+        hostAliases.put(ZK1_ALIAS, ZK1_IP);
 
-        when(ia.getCanonicalHostName()).thenReturn(ZK1_FQDN);
+        HostResolutionRequestInterceptor.INSTANCE.install(
+                new MappedHostResolver(hostAliases),
+                DefaultHostResolver.INSTANCE
+        );
 
+        InetAddress ia = InetAddress.getByName(ZK1_FQDN);
         IA_MOCK_ZK1 = ia;
     }
 
+    @AfterAll
+    public static void clearDNSMocks() {
+        HostResolutionRequestInterceptor.INSTANCE.uninstall();
+    }
+
     private static InetAddress getInetAddress(InetSocketAddress addr) {
         if (addr.getHostName().equals(ZK1_ALIAS) || addr.getHostName().equals(ZK1_IP)) {
             return IA_MOCK_ZK1;
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/StaticHostProviderTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/StaticHostProviderTest.java
index 905b6cd78..70460606a 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/test/StaticHostProviderTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/StaticHostProviderTest.java
@@ -30,11 +30,9 @@ import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
@@ -42,16 +40,42 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import org.apache.zookeeper.ZKTestCase;
 import org.apache.zookeeper.client.HostProvider;
 import org.apache.zookeeper.client.StaticHostProvider;
 import org.apache.zookeeper.common.Time;
+import org.burningwave.tools.net.DefaultHostResolver;
+import org.burningwave.tools.net.HostResolutionRequestInterceptor;
+import org.burningwave.tools.net.MappedHostResolver;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 public class StaticHostProviderTest extends ZKTestCase {
 
+    @BeforeAll
+    public static void setupDNSMocks() {
+        Map<String, String> hostAliases = new LinkedHashMap<>();
+        hostAliases.put("site1.mock", "192.168.1.1");
+        hostAliases.put("site2.mock", "192.168.1.2");
+        hostAliases.put("site3.mock", "192.168.1.3");
+        hostAliases.put("site4.mock", "192.168.1.4");
+
+        HostResolutionRequestInterceptor.INSTANCE.install(
+                new MappedHostResolver(hostAliases),
+                DefaultHostResolver.INSTANCE
+        );
+    }
+
+    @AfterAll
+    public static void clearDNSMocks() {
+        HostResolutionRequestInterceptor.INSTANCE.uninstall();
+    }
+
     private Random r = new Random(1);
 
     @Test
@@ -704,10 +728,7 @@ public class StaticHostProviderTest extends ZKTestCase {
         // Test a hostname that resolves to a single address
         list.add(InetSocketAddress.createUnresolved("issues.apache.org", 1234));
 
-        final InetAddress issuesApacheOrg = mock(InetAddress.class);
-        when(issuesApacheOrg.getHostAddress()).thenReturn("192.168.1.1");
-        when(issuesApacheOrg.toString()).thenReturn("issues.apache.org");
-        when(issuesApacheOrg.getHostName()).thenReturn("issues.apache.org");
+        final InetAddress issuesApacheOrg = InetAddress.getByName("site1.mock");
 
         StaticHostProvider.Resolver resolver = new StaticHostProvider.Resolver() {
             @Override
@@ -738,15 +759,9 @@ public class StaticHostProviderTest extends ZKTestCase {
         // Test a hostname that resolves to multiple addresses
         list.add(InetSocketAddress.createUnresolved("www.apache.org", 1234));
 
-        final InetAddress apacheOrg1 = mock(InetAddress.class);
-        when(apacheOrg1.getHostAddress()).thenReturn("192.168.1.1");
-        when(apacheOrg1.toString()).thenReturn("www.apache.org");
-        when(apacheOrg1.getHostName()).thenReturn("www.apache.org");
+        final InetAddress apacheOrg1 = InetAddress.getByName("site1.mock");
 
-        final InetAddress apacheOrg2 = mock(InetAddress.class);
-        when(apacheOrg2.getHostAddress()).thenReturn("192.168.1.2");
-        when(apacheOrg2.toString()).thenReturn("www.apache.org");
-        when(apacheOrg2.getHostName()).thenReturn("www.apache.org");
+        final InetAddress apacheOrg2 = InetAddress.getByName("site2.mock");
 
         final List<InetAddress> resolvedAddresses = new ArrayList<InetAddress>();
         resolvedAddresses.add(apacheOrg1);
@@ -781,10 +796,7 @@ public class StaticHostProviderTest extends ZKTestCase {
         final List<InetAddress> resolvedAddresses = new ArrayList<InetAddress>();
         for (int i = 0; i < 3; i++) {
             ipList.add(String.format("192.168.1.%d", i + 1));
-            final InetAddress apacheOrg = mock(InetAddress.class);
-            when(apacheOrg.getHostAddress()).thenReturn(String.format("192.168.1.%d", i + 1));
-            when(apacheOrg.toString()).thenReturn(String.format("192.168.1.%d", i + 1));
-            when(apacheOrg.getHostName()).thenReturn("www.apache.org");
+            final InetAddress apacheOrg = InetAddress.getByName("site" + (i + 1) + ".mock");
             resolvedAddresses.add(apacheOrg);
         }
 
@@ -826,10 +838,7 @@ public class StaticHostProviderTest extends ZKTestCase {
         list.add(InetSocketAddress.createUnresolved("www.google.com", 1234));
         final List<InetAddress> resolvedAddresses = new ArrayList<InetAddress>();
 
-        final InetAddress apacheOrg1 = mock(InetAddress.class);
-        when(apacheOrg1.getHostAddress()).thenReturn("192.168.1.1");
-        when(apacheOrg1.toString()).thenReturn("www.apache.org");
-        when(apacheOrg1.getHostName()).thenReturn("www.apache.org");
+        final InetAddress apacheOrg1 = InetAddress.getByName("site1.mock");
 
         resolvedAddresses.add(apacheOrg1);