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

wangzhongxiang pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new c4aa0ae2ca test: add unit test for seata-discovery-eureka
c4aa0ae2ca is described below

commit c4aa0ae2ca6e9ea27109e69336ca747662745065
Author: wjwang00 <wjwan...@foxmail.com>
AuthorDate: Tue Mar 25 09:02:54 2025 +0800

    test: add unit test for seata-discovery-eureka
---
 .../eureka/CustomEurekaInstanceConfigTest.java     | 106 +++++++++++
 .../eureka/EurekaRegistryProviderTest.java         |  29 +++
 .../eureka/EurekaRegistryServiceImplTest.java      | 210 +++++++++++++++++++++
 .../src/test/resources/registry.conf               |  93 +++++++++
 4 files changed, 438 insertions(+)

diff --git 
a/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/CustomEurekaInstanceConfigTest.java
 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/CustomEurekaInstanceConfigTest.java
new file mode 100644
index 0000000000..075e6b3edf
--- /dev/null
+++ 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/CustomEurekaInstanceConfigTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.seata.discovery.registry.eureka;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class CustomEurekaInstanceConfigTest {
+    private CustomEurekaInstanceConfig config;
+
+    @BeforeEach
+    void setUp() {
+        config = new CustomEurekaInstanceConfig();
+    }
+
+    // test getInstanceId()
+    @Test
+    void testGetInstanceIdWhenSet() {
+        config.setInstanceId("custom-instance-id");
+        assertEquals("custom-instance-id", config.getInstanceId());
+    }
+
+    @Test
+    void testGetInstanceIdWhenNotSet() throws Exception {
+        String instanceId = (String) getConfigString("getInstanceId");
+        assertEquals(instanceId, config.getInstanceId());
+    }
+    // test getIpAddress()
+    @Test
+    void testGetIpAddressWhenSet() {
+        config.setIpAddress("192.168.1.1");
+        assertEquals("192.168.1.1", config.getIpAddress());
+    }
+
+    @Test
+    void testGetIpAddressWhenNotSet() throws Exception {
+        String ipAddress = (String) getConfigString("getIpAddress");
+        assertEquals(ipAddress, config.getIpAddress());
+    }
+
+    // test getNonSecurePort()
+    @Test
+    void testGetNonSecurePortWhenSet() {
+        config.setPort(9090);
+        assertEquals(9090, config.getNonSecurePort());
+    }
+
+    @Test
+    void testGetNonSecurePortWhenNotSet() throws Exception {
+        int  nonSecurePort = (int) getConfigString("getNonSecurePort");
+        assertEquals(nonSecurePort, config.getNonSecurePort());
+    }
+
+    // test getAppname()
+    @Test
+    void testGetAppnameWhenSet() {
+        config.setApplicationName("my-app");
+        assertEquals("my-app", config.getAppname());
+    }
+
+    @Test
+    void testGetAppnameWhenNotSet() throws Exception {
+        String appName = (String) getConfigString("getAppname");
+        assertEquals(appName, config.getAppname());
+    }
+
+    // test getHostName()
+    @Test
+    void testGetHostName() {
+        config.setIpAddress("192.168.1.100");
+        assertEquals("192.168.1.100", config.getHostName(true));
+        assertEquals("192.168.1.100", config.getHostName(false));
+    }
+
+    @Test
+    void testGetHostNameWhenIpAddressNotSet() throws Exception {
+        String ipAddress = (String) getConfigString("getIpAddress");
+        assertEquals(ipAddress, config.getHostName(false));
+    }
+
+
+    private Object getConfigString(String method) throws 
NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        Class<?> grandparentClass = 
config.getClass().getSuperclass().getSuperclass();
+        Method grandparentMethod = grandparentClass.getDeclaredMethod(method);
+        return grandparentMethod.invoke(config);
+    }
+
+}
+
diff --git 
a/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryProviderTest.java
 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryProviderTest.java
new file mode 100644
index 0000000000..21e1dce7b4
--- /dev/null
+++ 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryProviderTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.seata.discovery.registry.eureka;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EurekaRegistryProviderTest {
+
+    @Test
+    void testProvide(){
+        assertThat(new 
EurekaRegistryProvider()).isInstanceOf(EurekaRegistryProvider.class);
+    }
+}
diff --git 
a/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImplTest.java
 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImplTest.java
new file mode 100644
index 0000000000..ac6db51fcb
--- /dev/null
+++ 
b/discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImplTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.seata.discovery.registry.eureka;
+
+import com.netflix.appinfo.ApplicationInfoManager;
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClient;
+import com.netflix.discovery.EurekaEventListener;
+import com.netflix.discovery.shared.Application;
+import org.apache.seata.config.Configuration;
+import org.apache.seata.config.ConfigurationFactory;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.mockStatic;
+
+public class EurekaRegistryServiceImplTest {
+
+    private EurekaClient mockEurekaClient;
+    private ApplicationInfoManager mockAppInfoManager;
+    private Application mockApplication;
+    private InstanceInfo mockInstanceInfo;
+    private EurekaRegistryServiceImpl registryService;
+    EurekaEventListener mockEventListener;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        mockEurekaClient = mock(EurekaClient.class);
+        mockAppInfoManager = mock(ApplicationInfoManager.class);
+        mockApplication = mock(Application.class);
+        mockInstanceInfo = mock(InstanceInfo.class);
+        mockEventListener  = mock(EurekaEventListener.class);
+
+        resetSingleton();
+        registryService = EurekaRegistryServiceImpl.getInstance();
+        setStaticField(EurekaRegistryServiceImpl.class, "eurekaClient", 
mockEurekaClient);
+        setStaticField(EurekaRegistryServiceImpl.class, 
"applicationInfoManager", mockAppInfoManager);
+    }
+
+    @AfterAll
+    public static void tearDown() throws Exception {
+        resetSingleton();
+    }
+
+    private static void resetSingleton() throws Exception {
+        // Reset singleton and static fields
+        setStaticField(EurekaRegistryServiceImpl.class, "instance", null);
+        setStaticField(EurekaRegistryServiceImpl.class, 
"applicationInfoManager", null);
+        setStaticField(EurekaRegistryServiceImpl.class, "eurekaClient", null);
+        setStaticField(EurekaRegistryServiceImpl.class, "instanceConfig", 
null);
+        clearStaticMap(EurekaRegistryServiceImpl.class, 
"LISTENER_SERVICE_MAP");
+        clearStaticMap(EurekaRegistryServiceImpl.class, "CLUSTER_ADDRESS_MAP");
+        clearStaticMap(EurekaRegistryServiceImpl.class, "CLUSTER_LOCK");
+    }
+
+    @Test
+    public void testGetInstance() {
+        EurekaRegistryServiceImpl instance1 = 
EurekaRegistryServiceImpl.getInstance();
+        EurekaRegistryServiceImpl instance2 = 
EurekaRegistryServiceImpl.getInstance();
+        Assertions.assertEquals(instance1,instance2);
+    }
+
+    @Test
+    public void testRegister() throws Exception {
+        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8091);
+        registryService.register(address);
+        CustomEurekaInstanceConfig instanceConfig = getInstanceConfig();
+        Assertions.assertEquals( "127.0.0.1", instanceConfig.getIpAddress());
+        Assertions.assertEquals( "default", instanceConfig.getAppname());
+        
verify(mockAppInfoManager).setInstanceStatus(InstanceInfo.InstanceStatus.UP);
+    }
+
+    @Test
+    void testSubscribe() throws Exception {
+        String testCluster = "TEST_CLUSTER";
+        registryService.subscribe(testCluster, mockEventListener);
+
+        // Verify that the listener is added to LISTENER_SERVICE_MAP
+        ConcurrentMap<String, List<EurekaEventListener>> listenerMap = 
getStaticListenerMap();
+        Assertions.assertTrue(listenerMap.containsKey(testCluster));
+        
Assertions.assertTrue(listenerMap.get(testCluster).contains(mockEventListener));
+
+        // Verify that the EurekaClient has registered the listener
+        verify(mockEurekaClient, 
times(1)).registerEventListener(mockEventListener);
+    }
+
+    @Test
+    void testUnsubscribe() throws Exception {
+        String testCluster = "TEST_CLUSTER";
+        registryService.subscribe(testCluster, mockEventListener);
+        registryService.unsubscribe(testCluster, mockEventListener);
+
+        // Verify that the listener is removed from LISTENER_SERVICE_MAP
+        ConcurrentMap<String, List<EurekaEventListener>> listenerMap = 
getStaticListenerMap();
+        Assertions.assertFalse(listenerMap.getOrDefault(testCluster, 
Collections.emptyList()).contains(mockEventListener));
+
+        // Verify that the EurekaClient has deregistered the listener
+        verify(mockEurekaClient, 
times(1)).unregisterEventListener(mockEventListener);
+    }
+
+    @Test
+    void testUnsubscribeWithNoExistingListeners() throws Exception {
+        String testCluster = "NON_EXISTENT_CLUSTER";
+        registryService.unsubscribe(testCluster, mockEventListener);
+        verify(mockEurekaClient).unregisterEventListener(any());
+    }
+
+    @Test
+    public void testUnregister() throws Exception {
+        registryService.unregister(new InetSocketAddress("127.0.0.1", 8091));
+        
verify(mockAppInfoManager).setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
+    }
+
+@Test
+    public void testLookup() throws Exception {
+    Configuration mockConfig = mock(Configuration.class);
+    
when(mockConfig.getConfig("service.vgroupMapping.test-group")).thenReturn("TEST-CLUSTER");
+
+    try (MockedStatic<ConfigurationFactory> mockedFactory = 
mockStatic(ConfigurationFactory.class)) {
+        
mockedFactory.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
+
+        // Mock Eureka to return the application instance
+        
when(mockEurekaClient.getApplication("TEST-CLUSTER")).thenReturn(mockApplication);
+        
when(mockApplication.getInstances()).thenReturn(Collections.singletonList(mockInstanceInfo));
+        
when(mockInstanceInfo.getStatus()).thenReturn(InstanceInfo.InstanceStatus.UP);
+        when(mockInstanceInfo.getIPAddr()).thenReturn("192.168.1.1");
+        when(mockInstanceInfo.getPort()).thenReturn(8091);
+
+        List<InetSocketAddress> addresses = 
registryService.lookup("test-group");
+
+        // Verify whether the transactionServiceGroup is set correctly
+        Field serviceGroupField = 
EurekaRegistryServiceImpl.class.getDeclaredField("transactionServiceGroup");
+        serviceGroupField.setAccessible(true);
+        String actualServiceGroup = (String) 
serviceGroupField.get(registryService);
+        Assertions.assertEquals("test-group", actualServiceGroup);
+        Assertions.assertNotNull(addresses);
+        Assertions.assertEquals(1, addresses.size());
+        Assertions.assertEquals(new InetSocketAddress("192.168.1.1", 8091), 
addresses.get(0));
+    }
+}
+
+    @Test
+    public void testClose() throws Exception {
+        registryService.close();
+        verify(mockEurekaClient).shutdown();
+        Assertions.assertNull(getStaticField(EurekaRegistryServiceImpl.class, 
"eurekaClient"));
+        Assertions.assertNull(getStaticField(EurekaRegistryServiceImpl.class, 
"applicationInfoManager"));
+    }
+
+    // Helper method: Set static fields via reflection
+    private static void setStaticField(Class<?> clazz, String fieldName, 
Object value) throws Exception {
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        field.set(null, value);
+    }
+
+    // Helper method: Get the value of a static field
+    @SuppressWarnings("unchecked")
+    private static <T> T getStaticField(Class<?> clazz, String fieldName) 
throws Exception {
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        return (T) field.get(null);
+    }
+
+
+    private static void clearStaticMap(Class<?> clazz, String fieldName) 
throws Exception {
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        ((ConcurrentMap<?, ?>) field.get(null)).clear();
+    }
+
+
+    private CustomEurekaInstanceConfig getInstanceConfig() throws Exception {
+        return getStaticField(EurekaRegistryServiceImpl.class, 
"instanceConfig");
+    }
+
+    @SuppressWarnings("unchecked")
+    private static ConcurrentMap<String, List<EurekaEventListener>> 
getStaticListenerMap() throws Exception {
+        Field field = 
EurekaRegistryServiceImpl.class.getDeclaredField("LISTENER_SERVICE_MAP");
+        field.setAccessible(true);
+        return (ConcurrentMap<String, List<EurekaEventListener>>) 
field.get(null);
+    }
+}
\ No newline at end of file
diff --git a/discovery/seata-discovery-eureka/src/test/resources/registry.conf 
b/discovery/seata-discovery-eureka/src/test/resources/registry.conf
new file mode 100644
index 0000000000..d229acd77c
--- /dev/null
+++ b/discovery/seata-discovery-eureka/src/test/resources/registry.conf
@@ -0,0 +1,93 @@
+#
+# 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.
+#
+
+registry {
+  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
+  type = "eureka"
+
+  nacos {
+    application = "seata-server"
+    serverAddr = "localhost"
+    namespace = ""
+    cluster = "default"
+  }
+  eureka {
+    serviceUrl = "http://localhost:8761/eureka";
+    application = "default"
+    weight = "1"
+  }
+  redis {
+    serverAddr = "localhost:6379"
+    db = "0"
+  }
+  zk {
+    cluster = "default"
+    serverAddr = "127.0.0.1:2181"
+    sessionTimeout = 6000
+    connectTimeout = 2000
+  }
+  consul {
+    cluster = "default"
+    serverAddr = "127.0.0.1:8500"
+  }
+  etcd3 {
+    cluster = "default"
+    serverAddr = "http://localhost:2379";
+  }
+  sofa {
+    serverAddr = "127.0.0.1:9603"
+    application = "default"
+    region = "DEFAULT_ZONE"
+    datacenter = "DefaultDataCenter"
+    cluster = "default"
+    group = "SEATA_GROUP"
+    addressWaitTime = "3000"
+  }
+  file {
+    name = "file.conf"
+  }
+}
+
+config {
+  # file、nacos 、apollo、zk、consul、etcd3
+  type = "file"
+
+  nacos {
+    serverAddr = "localhost"
+    namespace = ""
+    group = "SEATA_GROUP"
+  }
+  consul {
+    serverAddr = "127.0.0.1:8500"
+  }
+  apollo {
+    appId = "seata-server"
+    apolloMeta = "http://192.168.1.204:8801";
+    namespace = "application"
+  }
+  zk {
+    serverAddr = "127.0.0.1:2181"
+    sessionTimeout = 6000
+    connectTimeout = 2000
+  }
+  etcd3 {
+    serverAddr = "http://localhost:2379";
+  }
+  file {
+    name = "file.conf"
+  }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org
For additional commands, e-mail: notifications-h...@seata.apache.org

Reply via email to