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

hefengen 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 63e463ae99 [type: test] Add unit test for NacosDiscoveryService (#5310)
63e463ae99 is described below

commit 63e463ae994f934ed920b074449bc1d17c05f2f7
Author: lulu <1534972...@qq.com>
AuthorDate: Tue Nov 21 13:23:16 2023 +0800

    [type: test] Add unit test for NacosDiscoveryService (#5310)
    
    * [type:test] add unit test for NacosDiscoveryService
    
    * [type:test] Add the statement at the beginning
    
    * trigger ci
    
    * test ci
    
    * test ci
    
    * test ci
    
    * test ci
    
    ---------
    
    Co-authored-by: xiaoyu <xia...@apache.org>
---
 .../admin/model/enums/DiscoveryTypeEnum.java       |   4 +-
 .../discovery/nacos/NacosDiscoveryService.java     |  10 +-
 .../discovery/nacos/NacosDiscoveryServiceTest.java | 242 +++++++++++++++++++++
 3 files changed, 251 insertions(+), 5 deletions(-)

diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/enums/DiscoveryTypeEnum.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/enums/DiscoveryTypeEnum.java
index 9aab9dd19a..1f32816bef 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/enums/DiscoveryTypeEnum.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/enums/DiscoveryTypeEnum.java
@@ -47,9 +47,9 @@ public enum DiscoveryTypeEnum {
     ETCD("etcd"),
 
     /**
-     * consul.
+     * eureka.
      */
-    CONSUL("consul");
+    EUREKA("eureka");
 
     /**
      * Discovery type.
diff --git 
a/shenyu-discovery/shenyu-discovery-nacos/src/main/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryService.java
 
b/shenyu-discovery/shenyu-discovery-nacos/src/main/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryService.java
index 3708b1809c..535f437d9f 100644
--- 
a/shenyu-discovery/shenyu-discovery-nacos/src/main/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryService.java
+++ 
b/shenyu-discovery/shenyu-discovery-nacos/src/main/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryService.java
@@ -18,6 +18,7 @@
 package org.apache.shenyu.discovery.nacos;
 
 import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
 import org.apache.shenyu.common.utils.GsonUtils;
 import com.alibaba.nacos.api.PropertyKeyConst;
 import com.alibaba.nacos.api.exception.NacosException;
@@ -133,9 +134,12 @@ public class NacosDiscoveryService implements 
ShenyuDiscoveryService {
             Instance instance = GsonUtils.getInstance().fromJson(value, 
Instance.class);
             namingService.registerInstance(key, groupName, instance);
             LOGGER.info("Registering service with key: {} and value: {}", key, 
value);
-        } catch (NacosException e) {
-            LOGGER.error("Error registering Nacos service instance: {}", 
e.getMessage(), e);
-            throw new ShenyuException(e);
+        } catch (JsonSyntaxException jsonSyntaxException) {
+            LOGGER.error("The json format of value is wrong: {}", 
jsonSyntaxException.getMessage(), jsonSyntaxException);
+            throw new ShenyuException(jsonSyntaxException);
+        } catch (NacosException nacosException) {
+            LOGGER.error("Error registering Nacos service instance: {}", 
nacosException.getMessage(), nacosException);
+            throw new ShenyuException(nacosException);
         }
     }
 
diff --git 
a/shenyu-discovery/shenyu-discovery-nacos/src/test/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryServiceTest.java
 
b/shenyu-discovery/shenyu-discovery-nacos/src/test/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryServiceTest.java
new file mode 100644
index 0000000000..beee3e816a
--- /dev/null
+++ 
b/shenyu-discovery/shenyu-discovery-nacos/src/test/java/org/apache/shenyu/discovery/nacos/NacosDiscoveryServiceTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.discovery.nacos;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.NamingFactory;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.listener.EventListener;
+import com.alibaba.nacos.api.naming.listener.NamingEvent;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.google.gson.JsonObject;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.discovery.api.config.DiscoveryConfig;
+import org.apache.shenyu.discovery.api.listener.DataChangedEventListener;
+import org.apache.shenyu.discovery.api.listener.DiscoveryDataChangedEvent;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * The test for  {@link NacosDiscoveryService} .
+ */
+class NacosDiscoveryServiceTest {
+
+    private NacosDiscoveryService nacosDiscoveryServiceUnderTest;
+
+    private NamingService namingService;
+
+    @BeforeEach
+    void setUp() throws NoSuchFieldException, IllegalAccessException {
+        nacosDiscoveryServiceUnderTest = new NacosDiscoveryService();
+        namingService = mock(NamingService.class);
+        setField(nacosDiscoveryServiceUnderTest.getClass(), "namingService", 
namingService);
+        setField(nacosDiscoveryServiceUnderTest.getClass(), "groupName", 
"SHENYU_GROUP");
+    }
+
+    private <T> void setField(final Class<T> clazz, final String fieldName, 
final Object value) throws NoSuchFieldException, IllegalAccessException {
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        field.set(nacosDiscoveryServiceUnderTest, value);
+        field.setAccessible(false);
+    }
+
+    private <T> Object getField(final T object, final String fieldName) throws 
NoSuchFieldException, IllegalAccessException {
+        Class<?> clazz = object.getClass();
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        Object value = field.get(object);
+        field.setAccessible(false);
+        return value;
+    }
+
+    @Test
+    void testInit() throws NoSuchFieldException, IllegalAccessException {
+        // Set the discovery config
+        setField(nacosDiscoveryServiceUnderTest.getClass(), "namingService", 
null);
+        DiscoveryConfig config = new DiscoveryConfig();
+        Properties properties = new Properties();
+        config.setServerList("127.0.0.1:8848");
+        properties.setProperty("groupName", "SHENYU_GROUP");
+        config.setProps(properties);
+
+        NamingService mockedNamingService = mock(NamingService.class);
+        try (MockedStatic<NamingFactory> mockedNamingFactory = 
mockStatic(NamingFactory.class)) {
+            // Mock the successful creation of NamingService
+            mockedNamingFactory.when(() -> 
NamingFactory.createNamingService(any(Properties.class)))
+                    .thenReturn(mockedNamingService);
+            nacosDiscoveryServiceUnderTest.init(config);
+            mockedNamingFactory.verify(() -> 
NamingFactory.createNamingService(any(Properties.class)));
+            assertEquals(mockedNamingService, 
getField(nacosDiscoveryServiceUnderTest, "namingService"));
+            // Mock the situation where NamingService fails to be created and 
throws an exception
+            mockedNamingFactory.when(() -> 
NamingFactory.createNamingService(any(Properties.class)))
+                    .thenThrow(new NacosException());
+            assertThrows(ShenyuException.class, () -> 
nacosDiscoveryServiceUnderTest.init(config));
+        }
+    }
+
+    @Test
+    void testWatch() throws NacosException, NoSuchFieldException, 
IllegalAccessException {
+        final DataChangedEventListener mockListener = 
mock(DataChangedEventListener.class);
+        // Construct instance information
+        final String key = "test";
+        final String key2 = "test2";
+        Instance instance1 = new Instance();
+        instance1.setIp("192.168.1.1");
+        instance1.setPort(8080);
+        instance1.setServiceName(key);
+        instance1.setInstanceId(key);
+
+        Instance instance2 = new Instance();
+        instance2.setIp("192.168.1.2");
+        instance2.setPort(8081);
+        instance2.setServiceName(key2);
+        instance2.setInstanceId(key2);
+
+        List<Instance> initialInstances = new ArrayList<>();
+        initialInstances.add(instance1);
+        List<Instance> updatedInstances = Arrays.asList(instance1, instance2);
+
+        // Mock the behavior of namingService.subscribe
+        when(namingService.selectInstances(key, "SHENYU_GROUP", true))
+                .thenReturn(initialInstances)
+                .thenReturn(updatedInstances);
+        doAnswer(invocation -> {
+            EventListener nacosListener = invocation.getArgument(2);
+            NamingEvent event = new NamingEvent(key, updatedInstances);
+            nacosListener.onEvent(event);
+            return null;
+        }).when(namingService).subscribe(anyString(), anyString(), 
any(EventListener.class));
+        nacosDiscoveryServiceUnderTest.watch(key, mockListener);
+        // Verify that methods are called correctly
+        verify(mockListener, 
atLeastOnce()).onChange(any(DiscoveryDataChangedEvent.class));
+        verify(namingService).subscribe(anyString(), anyString(), 
any(EventListener.class));
+        verify(namingService, times(2)).selectInstances(key, "SHENYU_GROUP", 
true);
+        // Verify the field content of listenerMap:it should be non-empty
+        ConcurrentMap<String, EventListener> listenerMap = 
(ConcurrentMap<String, EventListener>) getField(nacosDiscoveryServiceUnderTest, 
"listenerMap");
+        assertNotNull(listenerMap.get(key));
+    }
+
+    @Test
+    void testUnwatch() throws NoSuchFieldException, IllegalAccessException {
+        final String key = "test";
+        nacosDiscoveryServiceUnderTest.unwatch(key);
+        ConcurrentMap<String, EventListener> listenerMap = 
(ConcurrentMap<String, EventListener>) getField(nacosDiscoveryServiceUnderTest, 
"listenerMap");
+        assertFalse(listenerMap.containsKey(key));
+    }
+
+    @Test
+    void testRegister() throws NacosException {
+        final String key = "test";
+        final String value = 
"{\"instanceId\":\"1\",\"serviceName\":\"exampleService\",\"ip\":\"127.0.0.1\",\"port\":8080}";
+
+        doNothing().when(namingService).registerInstance(anyString(), 
anyString(), any(Instance.class));
+        nacosDiscoveryServiceUnderTest.register(key, value);
+        // Verify whether the method is called correctly
+        verify(namingService).registerInstance(anyString(), anyString(), 
any(Instance.class));
+        // Mock the wrong json format
+        assertThrows(ShenyuException.class, () -> 
nacosDiscoveryServiceUnderTest.register(key, "test"));
+        // Mock the throwing of registerInstance exception
+        doThrow(new 
NacosException()).when(namingService).registerInstance(anyString(), 
anyString(), any(Instance.class));
+        assertThrows(ShenyuException.class, () -> 
nacosDiscoveryServiceUnderTest.register(key, value));
+    }
+
+    @Test
+    void testGetRegisterData() throws NacosException {
+        final String key = "test";
+        Instance instance1 = new Instance();
+        instance1.setIp("192.168.1.1");
+        instance1.setPort(8080);
+
+        Instance instance2 = new Instance();
+        instance2.setIp("192.168.1.2");
+        instance2.setPort(8081);
+
+        final List<Instance> mockInstances = Arrays.asList(instance1, 
instance2);
+        when(namingService.selectInstances(key, "SHENYU_GROUP", 
true)).thenReturn(mockInstances);
+        final List<String> result = 
nacosDiscoveryServiceUnderTest.getRegisterData(key);
+        verify(namingService).selectInstances(key, "SHENYU_GROUP", true);
+
+        // Verify that the data format is consistent
+        assertEquals(mockInstances.size(), result.size());
+        for (int i = 0; i < mockInstances.size(); i++) {
+            Instance instance = mockInstances.get(i);
+            String expectedJson = buildInstanceInfoJson(instance);
+            assertEquals(expectedJson, result.get(i));
+        }
+    }
+
+    @Test
+    void testExists() throws NacosException {
+        List<Instance> mockInstances = new ArrayList<>();
+        mockInstances.add(mock(Instance.class));
+        // Mock this service exists
+        when(namingService.selectInstances(anyString(), anyString(), 
anyBoolean())).thenReturn(mockInstances);
+        assertTrue(nacosDiscoveryServiceUnderTest.exists("key"));
+        // Mock the service does not exist
+        when(namingService.selectInstances(anyString(), anyString(), 
anyBoolean())).thenReturn(Collections.emptyList());
+        assertFalse(nacosDiscoveryServiceUnderTest.exists("key"));
+        // Mock the throwing of NacosException
+        when(namingService.selectInstances(anyString(), anyString(), 
anyBoolean())).thenThrow(new NacosException());
+        assertThrows(ShenyuException.class, () -> 
nacosDiscoveryServiceUnderTest.exists("key"));
+    }
+
+    /**
+     * Same as in NacosDiscoveryService.
+     *
+     * @param instance Convert Nacos instance to Json string
+     */
+    private String buildInstanceInfoJson(final Instance instance) {
+        JsonObject instanceJson = new JsonObject();
+        instanceJson.addProperty("url", instance.getIp() + ":" + 
instance.getPort());
+        // status 0:true, 1:false
+        instanceJson.addProperty("status", instance.isHealthy() ? 0 : 1);
+        instanceJson.addProperty("weight", instance.getWeight());
+
+        return GsonUtils.getInstance().toJson(instanceJson);
+    }
+
+}
+

Reply via email to