use random zookeeper port in unit test (#604)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ccc7afa..3e8a2db 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,6 +8,7 @@
     strategy:
       matrix:
         java: [ 8, 11 ]
+    timeout-minutes: 20
     steps:
       - uses: actions/checkout@v2
       - name: Set up JDK ${{ matrix.java }}
diff --git a/dubbo-admin-server/src/main/resources/application-test.properties b/dubbo-admin-server/src/main/resources/application-test.properties
index 075c357..dce770a 100644
--- a/dubbo-admin-server/src/main/resources/application-test.properties
+++ b/dubbo-admin-server/src/main/resources/application-test.properties
@@ -16,7 +16,7 @@
 #
 
 # centers in dubbo2.7
-admin.registry.address=zookeeper://127.0.0.1:2182
-admin.config-center=zookeeper://127.0.0.1:2182
-admin.metadata.address=zookeeper://127.0.0.1:2182
-admin.check.authority=false
\ No newline at end of file
+admin.registry.address=zookeeper://127.0.0.1:2183
+admin.config-center=zookeeper://127.0.0.1:2183
+admin.metadata.address=zookeeper://127.0.0.1:2183
+admin.check.authority=false
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
index 074373f..9448a93 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
@@ -26,35 +26,56 @@
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.web.client.TestRestTemplate;
 import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.TestPropertySourceUtils;
+import org.springframework.util.SocketUtils;
 
 @ActiveProfiles("test")
 @RunWith(SpringJUnit4ClassRunner.class)
 @SpringBootTest(classes = DubboAdminApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@ContextConfiguration(classes = DubboAdminApplication.class)
+@ContextConfiguration(classes = DubboAdminApplication.class, initializers = AbstractSpringIntegrationTest.PropertyOverrideContextInitializer.class)
 public abstract class AbstractSpringIntegrationTest {
-  @Autowired
-  protected TestRestTemplate restTemplate;
+    @Autowired
+    protected TestRestTemplate restTemplate;
 
-  protected static final TestingServer zkServer;
-  protected static final CuratorFramework zkClient;
+    protected static final TestingServer zkServer;
+    protected static final CuratorFramework zkClient;
 
-  static {
-    try {
-      zkServer = new TestingServer(2182, true);
-      zkClient = CuratorFrameworkFactory.newClient(zkServer.getConnectString(), new RetryOneTime(2000));
-      zkClient.start();
-    } catch (Exception e) {
-      throw new ExceptionInInitializerError(e);
+    static {
+        try {
+            int zkPort = SocketUtils.findAvailableTcpPort();
+            zkServer = new TestingServer(zkPort, true);
+            zkClient = CuratorFrameworkFactory.newClient(zkServer.getConnectString(), new RetryOneTime(2000));
+            zkClient.start();
+        } catch (Exception e) {
+            throw new ExceptionInInitializerError(e);
+        }
     }
-  }
 
-  @LocalServerPort
-  protected int port;
+    @LocalServerPort
+    protected int port;
 
-  protected String url(final String path) {
-    return "http://localhost:" + port + path;
-  }
+    protected String url(final String path) {
+        return "http://localhost:" + port + path;
+    }
+
+    public static class PropertyOverrideContextInitializer
+            implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+
+        static final String PROPERTY_FIRST_VALUE = "contextClass";
+
+        @Override
+        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
+            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
+                    "admin.registry.address=zookeeper://" + zkServer.getConnectString());
+            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
+                    "admin.metadata.address=zookeeper://" + zkServer.getConnectString());
+            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
+                    "admin.config-center=zookeeper://" + zkServer.getConnectString());
+        }
+    }
 }