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

liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new e00098b2bf feat: add infra-etcd unit test (#6087)
e00098b2bf is described below

commit e00098b2bff36117c991ba3b7d7ac69272a34fd0
Author: shown <[email protected]>
AuthorDate: Thu Aug 7 22:32:49 2025 +0800

    feat: add infra-etcd unit test (#6087)
---
 .../shenyu-admin-listener-etcd/pom.xml             |   4 -
 .../config/properties/EtcdPropertiesTest.java      |  48 -----
 .../shenyu/admin/listener/etcd/EtcdClientTest.java |  93 ---------
 shenyu-infra/shenyu-infra-etcd/pom.xml             |  13 ++
 .../infra/etcd/autoconfig/EtcdConfiguration.java   |   2 +
 .../infra/etcd/autoconfig/EtcdPropertiesTest.java  |  53 ++++++
 .../shenyu/infra/etcd/client/EtcdClientTest.java   | 137 ++++++++++++++
 .../shenyu/sync/data/etcd/EtcdClientTest.java      | 210 ---------------------
 8 files changed, 205 insertions(+), 355 deletions(-)

diff --git a/shenyu-admin-listener/shenyu-admin-listener-etcd/pom.xml 
b/shenyu-admin-listener/shenyu-admin-listener-etcd/pom.xml
index ce28ded084..ce433ce7de 100644
--- a/shenyu-admin-listener/shenyu-admin-listener-etcd/pom.xml
+++ b/shenyu-admin-listener/shenyu-admin-listener-etcd/pom.xml
@@ -27,10 +27,6 @@
     <artifactId>shenyu-admin-listener-etcd</artifactId>
 
     <dependencies>
-        <dependency>
-            <artifactId>grpc-netty</artifactId>
-            <groupId>io.grpc</groupId>
-        </dependency>
 
         <dependency>
             <groupId>org.apache.shenyu</groupId>
diff --git 
a/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/config/properties/EtcdPropertiesTest.java
 
b/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/config/properties/EtcdPropertiesTest.java
deleted file mode 100644
index d4b62153e9..0000000000
--- 
a/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/config/properties/EtcdPropertiesTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.admin.config.properties;
-
-import org.apache.shenyu.infra.etcd.autoconfig.EtcdProperties;
-import org.apache.shenyu.infra.etcd.config.EtcdConfig;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * Test cases for {@link EtcdProperties}.
- */
-public class EtcdPropertiesTest {
-    
-    @Test
-    public void etcdPropertiesTest() {
-
-        final EtcdProperties etcdProperties = new EtcdProperties();
-        etcdProperties.setEtcd(
-                EtcdConfig.builder()
-                        .url("url")
-                        .sessionTimeout(0)
-                        .connectionTimeout(0)
-                        .serializer("serializer")
-                        .build()
-        );
-
-        Assertions.assertEquals(etcdProperties.getEtcd().getUrl(), "url");
-        Assertions.assertEquals(etcdProperties.getEtcd().getSerializer(), 
"serializer");
-        
Assertions.assertEquals(etcdProperties.getEtcd().getConnectionTimeout(), 0);
-        Assertions.assertEquals(etcdProperties.getEtcd().getSessionTimeout(), 
0);
-    }
-}
diff --git 
a/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/listener/etcd/EtcdClientTest.java
 
b/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/listener/etcd/EtcdClientTest.java
deleted file mode 100644
index 89b275d1d8..0000000000
--- 
a/shenyu-admin-listener/shenyu-admin-listener-etcd/src/test/java/org/apache/shenyu/admin/listener/etcd/EtcdClientTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.admin.listener.etcd;
-
-import org.apache.shenyu.infra.etcd.client.EtcdClient;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import java.nio.charset.StandardCharsets;
-import java.util.concurrent.CompletableFuture;
-import io.etcd.jetcd.ByteSequence;
-import io.etcd.jetcd.Client;
-import io.etcd.jetcd.KV;
-import io.etcd.jetcd.kv.DeleteResponse;
-import io.etcd.jetcd.kv.PutResponse;
-import io.etcd.jetcd.options.DeleteOption;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * The testCase for {@link EtcdClient}.
- */
-@ExtendWith(MockitoExtension.class)
-public class EtcdClientTest {
-
-    private static final String TEST_KEY = "KEY";
-
-    private static final String TEST_VALUE = "VALUE";
-
-    @Mock
-    private Client client;
-
-    private EtcdClient etcdClient;
-
-    @BeforeEach
-    public void setUp() {
-        KV kvClient = mock(KV.class);
-        when(client.getKVClient()).thenReturn(kvClient);
-        etcdClient = EtcdClient.builder().client(client).build();
-        assertNotNull(etcdClient);
-    }
-
-    @AfterEach
-    public void close() {
-        etcdClient.close();
-    }
-
-    @Test
-    public void put() {
-        CompletableFuture<PutResponse> put = mock(CompletableFuture.class);
-        when(client.getKVClient().put(ByteSequence.from(TEST_KEY, 
StandardCharsets.UTF_8), ByteSequence.from(TEST_VALUE, 
StandardCharsets.UTF_8))).thenReturn(put);
-        etcdClient.put(TEST_KEY, TEST_VALUE);
-        verify(client.getKVClient(), times(1)).put(any(ByteSequence.class), 
any(ByteSequence.class));
-    }
-
-    @Test
-    public void delete() {
-        CompletableFuture<DeleteResponse> delete = 
mock(CompletableFuture.class);
-        when(client.getKVClient().delete(ByteSequence.from(TEST_KEY, 
StandardCharsets.UTF_8))).thenReturn(delete);
-        etcdClient.delete(TEST_KEY);
-        verify(client.getKVClient(), times(1)).delete(any(ByteSequence.class));
-    }
-
-    @Test
-    public void deleteEtcdPathRecursive() {
-        when(client.getKVClient().delete(any(ByteSequence.class), 
any(DeleteOption.class))).thenReturn(mock(CompletableFuture.class));
-        etcdClient.deleteEtcdPathRecursive(TEST_KEY);
-        verify(client.getKVClient(), times(1)).delete(any(ByteSequence.class), 
any(DeleteOption.class));
-    }
-}
diff --git a/shenyu-infra/shenyu-infra-etcd/pom.xml 
b/shenyu-infra/shenyu-infra-etcd/pom.xml
index 03ce9011eb..96f2f578a7 100644
--- a/shenyu-infra/shenyu-infra-etcd/pom.xml
+++ b/shenyu-infra/shenyu-infra-etcd/pom.xml
@@ -70,6 +70,19 @@
             <version>${grpc.version}</version>
         </dependency>
 
+        <dependency>
+            <artifactId>grpc-netty</artifactId>
+            <groupId>io.grpc</groupId>
+            <version>${grpc.version}</version>
+        </dependency>
+
+        <!-- Test -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
 </project>
diff --git 
a/shenyu-infra/shenyu-infra-etcd/src/main/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdConfiguration.java
 
b/shenyu-infra/shenyu-infra-etcd/src/main/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdConfiguration.java
index c01c782cc6..fb1e9d7d06 100644
--- 
a/shenyu-infra/shenyu-infra-etcd/src/main/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdConfiguration.java
+++ 
b/shenyu-infra/shenyu-infra-etcd/src/main/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdConfiguration.java
@@ -22,6 +22,7 @@ import org.apache.shenyu.infra.etcd.client.EtcdClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -41,6 +42,7 @@ public class EtcdConfiguration {
      * @return Etcd Client
      */
     @Bean
+    @ConditionalOnMissingBean
     public EtcdClient etcdClient(final EtcdProperties etcdProperties) {
 
         log.info("Initializing Etcd Client with URL: {}", 
etcdProperties.getEtcd().getUrl());
diff --git 
a/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdPropertiesTest.java
 
b/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdPropertiesTest.java
new file mode 100644
index 0000000000..c2899bf056
--- /dev/null
+++ 
b/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/autoconfig/EtcdPropertiesTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.infra.etcd.autoconfig;
+
+import org.apache.shenyu.infra.etcd.config.EtcdConfig;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class EtcdPropertiesTest {
+
+    @Test
+    public void testDefaultEtcdConfigValues() {
+        EtcdProperties etcdProperties = new EtcdProperties();
+        EtcdConfig etcdConfig = etcdProperties.getEtcd();
+
+        assertNotNull(etcdConfig, "EtcdConfig should not be null");
+        assertEquals(30 * 1000, etcdConfig.getConnectionTimeout(), "Default 
connection timeout should be 30 seconds");
+        assertEquals(30 * 1000, etcdConfig.getSessionTimeout(), "Default 
session timeout should be 30 seconds");
+    }
+
+    @Test
+    public void testSetEtcdConfig() {
+        EtcdProperties etcdProperties = new EtcdProperties();
+        EtcdConfig customConfig = EtcdConfig.builder()
+                .connectionTimeout(60 * 1000)
+                .sessionTimeout(60 * 1000)
+                .build();
+
+        etcdProperties.setEtcd(customConfig);
+        EtcdConfig etcdConfig = etcdProperties.getEtcd();
+
+        assertNotNull(etcdConfig, "EtcdConfig should not be null after 
setting");
+        assertEquals(60 * 1000, etcdConfig.getConnectionTimeout(), "Connection 
timeout should be updated to 60 seconds");
+        assertEquals(60 * 1000, etcdConfig.getSessionTimeout(), "Session 
timeout should be updated to 60 seconds");
+    }
+}
diff --git 
a/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/client/EtcdClientTest.java
 
b/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/client/EtcdClientTest.java
new file mode 100644
index 0000000000..bb5e3eb252
--- /dev/null
+++ 
b/shenyu-infra/shenyu-infra-etcd/src/test/java/org/apache/shenyu/infra/etcd/client/EtcdClientTest.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.infra.etcd.client;
+
+import io.etcd.jetcd.Client;
+import io.etcd.jetcd.ClientBuilder;
+import io.etcd.jetcd.KV;
+import io.etcd.jetcd.Lease;
+import io.etcd.jetcd.kv.PutResponse;
+import io.etcd.jetcd.lease.LeaseGrantResponse;
+import io.etcd.jetcd.lease.LeaseKeepAliveResponse;
+import io.grpc.stub.StreamObserver;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class EtcdClientTest {
+
+    @Test
+    public void etcdClientTest() {
+        try (MockedStatic<Client> clientMockedStatic = 
mockStatic(Client.class)) {
+            final ClientBuilder clientBuilder = mock(ClientBuilder.class);
+            clientMockedStatic.when(Client::builder).thenReturn(clientBuilder);
+            
when(clientBuilder.endpoints(anyString())).thenReturn(clientBuilder);
+            final Client client = mock(Client.class);
+            
when(clientBuilder.endpoints(anyString()).build()).thenReturn(client);
+            final Lease lease = mock(Lease.class);
+            when(client.getLeaseClient()).thenReturn(lease);
+            final CompletableFuture<LeaseGrantResponse> completableFuture = 
mock(CompletableFuture.class);
+            final LeaseGrantResponse leaseGrantResponse = 
mock(LeaseGrantResponse.class);
+
+            
when(client.getLeaseClient().grant(anyLong())).thenReturn(completableFuture);
+            when(completableFuture.get()).thenReturn(leaseGrantResponse);
+            Assertions.assertDoesNotThrow(() -> 
EtcdClient.builder().client(Client.builder().endpoints("url").build())).ttl(60L).timeout(3000L).build();
+
+            List<StreamObserver<LeaseKeepAliveResponse>> observerList = new 
ArrayList<>();
+            doAnswer(invocation -> {
+                observerList.add(invocation.getArgument(1));
+                return lease;
+            }).when(lease).keepAlive(anyLong(), any());
+            Assertions.assertDoesNotThrow(() -> 
EtcdClient.builder().client(Client.builder().endpoints("url").build())).ttl(60L).timeout(3000L).build();
+            final LeaseKeepAliveResponse leaseKeepAliveResponse = 
mock(LeaseKeepAliveResponse.class);
+            observerList.forEach(streamObserver -> {
+                streamObserver.onCompleted();
+                streamObserver.onError(new ShenyuException("test"));
+                streamObserver.onNext(leaseKeepAliveResponse);
+            });
+
+            doThrow(new 
InterruptedException("error")).when(completableFuture).get();
+            Assertions.assertDoesNotThrow(() -> 
EtcdClient.builder().client(Client.builder().endpoints("url").build())).ttl(60L).timeout(3000L).build();
+        } catch (Exception e) {
+            throw new ShenyuException(e.getCause());
+        }
+    }
+
+    @Test
+    public void closeTest() {
+        try (MockedStatic<Client> clientMockedStatic = 
mockStatic(Client.class)) {
+            this.mockEtcd(clientMockedStatic);
+            final EtcdClient etcdClient = 
EtcdClient.builder().client(Client.builder().endpoints("url").build()).ttl(60L).timeout(3000L).build();
+            etcdClient.close();
+        } catch (Exception e) {
+            throw new ShenyuException(e.getCause());
+        }
+    }
+
+    @Test
+    public void putEphemeralTest() {
+        try (MockedStatic<Client> clientMockedStatic = 
mockStatic(Client.class)) {
+            final Client client = this.mockEtcd(clientMockedStatic);
+            final KV mockKV = mock(KV.class);
+            when(client.getKVClient()).thenReturn(mockKV);
+            final CompletableFuture<PutResponse> completableFuture = 
mock(CompletableFuture.class);
+            when(mockKV.put(any(), any(), 
any())).thenReturn(completableFuture);
+            final PutResponse putResponse = mock(PutResponse.class);
+            when(completableFuture.get(anyLong(), 
any(TimeUnit.class))).thenReturn(putResponse);
+            final EtcdClient etcdClient = 
EtcdClient.builder().client(Client.builder().endpoints("url").build()).ttl(60L).timeout(3000L).build();
+            etcdClient.putEphemeral("key", "value");
+
+            doThrow(new 
InterruptedException("error")).when(completableFuture).get(anyLong(), 
any(TimeUnit.class));
+            etcdClient.putEphemeral("key", "value");
+        } catch (Exception e) {
+            throw new ShenyuException(e.getCause());
+        }
+    }
+
+    private Client mockEtcd(final MockedStatic<Client> clientMockedStatic) 
throws InterruptedException, ExecutionException {
+        final ClientBuilder clientBuilder = mock(ClientBuilder.class);
+        clientMockedStatic.when(Client::builder).thenReturn(clientBuilder);
+        when(clientBuilder.endpoints(anyString())).thenReturn(clientBuilder);
+        final Client client = mock(Client.class);
+        when(clientBuilder.endpoints(anyString()).build()).thenReturn(client);
+        final Lease lease = mock(Lease.class);
+        when(client.getLeaseClient()).thenReturn(lease);
+        final CompletableFuture<LeaseGrantResponse> completableFuture = 
mock(CompletableFuture.class);
+        final LeaseGrantResponse leaseGrantResponse = 
mock(LeaseGrantResponse.class);
+        
when(client.getLeaseClient().grant(anyLong())).thenReturn(completableFuture);
+        when(completableFuture.get()).thenReturn(leaseGrantResponse);
+        return client;
+    }
+
+}
diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-etcd/src/test/java/org/apache/shenyu/sync/data/etcd/EtcdClientTest.java
 
b/shenyu-sync-data-center/shenyu-sync-data-etcd/src/test/java/org/apache/shenyu/sync/data/etcd/EtcdClientTest.java
deleted file mode 100644
index 4bc647a82a..0000000000
--- 
a/shenyu-sync-data-center/shenyu-sync-data-etcd/src/test/java/org/apache/shenyu/sync/data/etcd/EtcdClientTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.sync.data.etcd;
-
-import com.google.protobuf.ByteString;
-import io.etcd.jetcd.ByteSequence;
-import io.etcd.jetcd.Client;
-import io.etcd.jetcd.KV;
-import io.etcd.jetcd.KeyValue;
-import io.etcd.jetcd.Watch;
-import io.etcd.jetcd.kv.GetResponse;
-import io.etcd.jetcd.options.WatchOption;
-import io.etcd.jetcd.watch.WatchEvent;
-import io.etcd.jetcd.watch.WatchResponse;
-import org.apache.shenyu.common.exception.ShenyuException;
-import org.apache.shenyu.infra.etcd.client.EtcdClient;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.mockito.junit.jupiter.MockitoSettings;
-import org.mockito.quality.Strictness;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * test case for {@link EtcdClient}.
- */
-@ExtendWith(MockitoExtension.class)
-@MockitoSettings(strictness = Strictness.LENIENT)
-public class EtcdClientTest {
-
-    private static final String KEY1 = "/foo/key1";
-
-    private static final String KEY2 = "/foo/key2";
-
-    private static final String VALUE = "value";
-
-    private static final String GET_KEY = "getKey";
-
-    private static final String PREFIX = "/foo";
-
-    private static final String SEPARATOR = "/";
-
-    private static final String EXPECTED1 = "key1";
-
-    private static final String EXPECTED2 = "key2";
-
-    private static final String WATCH_DATA_CHANGE_KEY = "watchDataChange";
-
-    private static final String WATCH_CHILD_CHANGE_KEY = "WatchChildChange";
-
-    @InjectMocks
-    private EtcdClient etcdClient;
-
-    @Mock
-    private Client client;
-
-    @Mock
-    private Watch.Watcher watcher;
-
-    @BeforeEach
-    public void setUp() {
-        KV kv = mock(KV.class);
-        final CompletableFuture<GetResponse> future = 
mock(CompletableFuture.class);
-        GetResponse getResponse = mock(GetResponse.class);
-        List<KeyValue> keyValues = new ArrayList<>(2);
-        KeyValue keyValue1 = mock(KeyValue.class);
-        KeyValue keyValue2 = mock(KeyValue.class);
-        keyValues.add(keyValue1);
-        keyValues.add(keyValue2);
-        final ByteString key1 = ByteString.copyFromUtf8(KEY1);
-        final ByteString key2 = ByteString.copyFromUtf8(KEY2);
-        final ByteString value1 = ByteString.copyFromUtf8(VALUE);
-
-        /**
-         *  mock get method.
-         */
-        when(client.getKVClient()).thenReturn(kv);
-        when(kv.get(any())).thenReturn(future);
-        try {
-            when(future.get()).thenReturn(getResponse);
-        } catch (Exception e) {
-            throw new ShenyuException(e.getCause());
-        }
-        when(getResponse.getKvs()).thenReturn(keyValues);
-        when(keyValue1.getValue()).thenReturn(ByteSequence.from(value1));
-        /**
-         * mock getChildrenKeys method.
-         */
-        when(kv.get(any(), any())).thenReturn(future);
-        when(keyValue1.getKey()).thenReturn(ByteSequence.from(key1));
-        when(keyValue2.getKey()).thenReturn(ByteSequence.from(key2));
-        /**
-         * mock watchDataChange method.
-         */
-        Watch watch = mock(Watch.class);
-        when(client.getWatchClient()).thenReturn(watch);
-        when(watch.watch(any(ByteSequence.class), 
any(Watch.Listener.class))).thenReturn(watcher);
-        /**
-         * mock watchChildChange method.
-         */
-        when(watch.watch(any(ByteSequence.class), any(WatchOption.class), 
any(Watch.Listener.class))).thenReturn(watcher);
-    }
-
-    @Test
-    public void testGet() {
-        String result = etcdClient.get(GET_KEY);
-        assertEquals(VALUE, result);
-    }
-
-    @Test
-    public void testGetChildrenKeys() throws Exception {
-        List<String> result = etcdClient.getChildrenKeys(PREFIX, SEPARATOR);
-        List<String> expected = new ArrayList<>();
-        expected.add(EXPECTED1);
-        expected.add(EXPECTED2);
-        assertEquals(expected, result);
-    }
-
-    @Test
-    public void testWatchDataChange() {
-        BiConsumer<String, String> updateHandler = mock(BiConsumer.class);
-        Consumer<String> deleteHandler = mock(Consumer.class);
-        etcdClient.watchDataChange(WATCH_DATA_CHANGE_KEY, updateHandler, 
deleteHandler);
-        etcdClient.watchClose(WATCH_DATA_CHANGE_KEY);
-        etcdClient.watchClose("not hit");
-        verify(watcher).close();
-    }
-    
-    @Test
-    public void testWatchChildChange() {
-        BiConsumer<String, String> updateHandler = mock(BiConsumer.class);
-        Consumer<String> deleteHandler = mock(Consumer.class);
-        etcdClient.watchChildChange(WATCH_CHILD_CHANGE_KEY, updateHandler, 
deleteHandler);
-        etcdClient.watchClose(WATCH_CHILD_CHANGE_KEY);
-        verify(watcher).close();
-    }
-
-    @Test
-    public void testEtcdClient() throws ExecutionException, 
InterruptedException {
-        final Client client = mock(Client.class);
-        final EtcdClient etcdClient = 
EtcdClient.builder().client(client).build();
-        assertDoesNotThrow(etcdClient::close);
-        final KV mockKV = mock(KV.class);
-        when(client.getKVClient()).thenReturn(mockKV);
-        final CompletableFuture<GetResponse> future = 
mock(CompletableFuture.class);
-        when(mockKV.get(any(ByteSequence.class))).thenReturn(future);
-        doThrow(new InterruptedException()).when(future).get();
-        assertDoesNotThrow(() -> etcdClient.get("key"));
-    }
-
-    @Test
-    public void watchTest() throws NoSuchMethodException, 
InvocationTargetException, IllegalAccessException {
-        BiConsumer<String, String> updateHandler = mock(BiConsumer.class);
-        Consumer<String> deleteHandler = mock(Consumer.class);
-        final Method watch = EtcdClient.class.getDeclaredMethod("watch", 
BiConsumer.class, Consumer.class);
-        watch.setAccessible(true);
-        final Watch.Listener listener = (Watch.Listener) 
watch.invoke(etcdClient, updateHandler, deleteHandler);
-        final WatchResponse watchResponse = mock(WatchResponse.class);
-        List<WatchEvent> watchEvents = new ArrayList<>(2);
-        final WatchEvent watchEvent = mock(WatchEvent.class);
-        watchEvents.add(watchEvent);
-        when(watchResponse.getEvents()).thenReturn(watchEvents);
-        final KeyValue keyValue = mock(KeyValue.class);
-        when(watchEvent.getKeyValue()).thenReturn(keyValue);
-        when(keyValue.getValue()).thenReturn(ByteSequence.from("value", 
StandardCharsets.UTF_8));
-        when(keyValue.getKey()).thenReturn(ByteSequence.from("key", 
StandardCharsets.UTF_8));
-        when(watchEvent.getEventType()).thenReturn(WatchEvent.EventType.PUT);
-        assertDoesNotThrow(() -> listener.onNext(watchResponse));
-        
when(watchEvent.getEventType()).thenReturn(WatchEvent.EventType.DELETE);
-        assertDoesNotThrow(() -> listener.onNext(watchResponse));
-        
when(watchEvent.getEventType()).thenReturn(WatchEvent.EventType.UNRECOGNIZED);
-        assertDoesNotThrow(() -> listener.onNext(watchResponse));
-    }
-
-}

Reply via email to