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

zhangyv 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 5a80340f60 test: add tests for DefaultResourceManager and 
ClusterWatcherManager (#7737)
5a80340f60 is described below

commit 5a80340f60b4ba6431a30467d167a8b5b951bb40
Author: lokidundun <[email protected]>
AuthorDate: Thu Oct 30 21:32:38 2025 +0800

    test: add tests for DefaultResourceManager and ClusterWatcherManager (#7737)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 .../namingserver/ClusterWatcherManagerTest.java    |  50 +++
 .../seata/rm/DefaultResourceManagerTest.java       | 355 +++++++++++++++++++++
 4 files changed, 407 insertions(+)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 6df7fab7ae..f77d017b7b 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -95,6 +95,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7718](https://github.com/apache/incubator-seata/pull/7718)] add UT for 
config module
 - [[#7723](https://github.com/apache/incubator-seata/pull/7723)] add UT for 
fastjson2 to test PostgreSQL Array type
 - [[#7731](https://github.com/apache/incubator-seata/pull/7731)] add UT for 
rm.fence
+- [[#7737](https://github.com/apache/incubator-seata/pull/7737)] add UT for 
DefaultResourceManager and ClusterWatcherManager
 
 
 ### refactor:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 83dfbf91f6..3e66207881 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -95,6 +95,7 @@
 - [[#7718](https://github.com/apache/incubator-seata/pull/7718)] 为config模块增加单测
 - [[#7723](https://github.com/apache/incubator-seata/pull/7723)] 添加 fastjson2 
的 UT 来测试 PostgreSQL 数组类型
 - [[#7731](https://github.com/apache/incubator-seata/pull/7731)] 
为rm.fence模块添加单测
+- [[#7737](https://github.com/apache/incubator-seata/pull/7737)] 为 
DefaultResourceManager 和 ClusterWatcherManager 添加测试方法
 
 ### refactor:
 
diff --git 
a/namingserver/src/test/java/org/apache/seata/namingserver/ClusterWatcherManagerTest.java
 
b/namingserver/src/test/java/org/apache/seata/namingserver/ClusterWatcherManagerTest.java
index 22e5e5de4f..51731a26f1 100644
--- 
a/namingserver/src/test/java/org/apache/seata/namingserver/ClusterWatcherManagerTest.java
+++ 
b/namingserver/src/test/java/org/apache/seata/namingserver/ClusterWatcherManagerTest.java
@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
 import org.springframework.test.util.ReflectionTestUtils;
 
 import javax.servlet.AsyncContext;
@@ -33,6 +34,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -206,4 +208,52 @@ public class ClusterWatcherManagerTest {
         assertEquals(TEST_TERM, term1);
         assertEquals(0L, term2);
     }
+
+    @Test
+    void testNotifyWithNotModifiedStatus() {
+        Watcher<AsyncContext> watcher =
+                new Watcher<>(TEST_GROUP, asyncContext, TEST_TIMEOUT, 
TEST_TERM, TEST_CLIENT_ENDPOINT);
+
+        ReflectionTestUtils.invokeMethod(clusterWatcherManager, "notify", 
watcher, HttpStatus.NOT_MODIFIED.value());
+
+        Mockito.verify(response).setStatus(HttpStatus.NOT_MODIFIED.value());
+        Mockito.verify(asyncContext).complete();
+        assertTrue(watcher.isDone());
+    }
+
+    @Test
+    void testScheduledTaskReRegisterNonTimeoutWatcher() throws 
InterruptedException {
+        long timeout = System.currentTimeMillis() + 3000;
+        Watcher<AsyncContext> watcher =
+                new Watcher<>(TEST_GROUP, asyncContext, (int) timeout, 
TEST_TERM, TEST_CLIENT_ENDPOINT);
+        clusterWatcherManager.registryWatcher(watcher);
+
+        clusterWatcherManager.init();
+        TimeUnit.SECONDS.sleep(2);
+
+        Mockito.verify(response, Mockito.never()).setStatus(Mockito.anyInt());
+        Mockito.verify(asyncContext, Mockito.never()).complete();
+        assertFalse(watcher.isDone());
+        Map<String, Queue<Watcher<?>>> watchers =
+                (Map<String, Queue<Watcher<?>>>) 
ReflectionTestUtils.getField(clusterWatcherManager, "WATCHERS");
+        assertTrue(watchers.containsKey(TEST_GROUP));
+        assertEquals(1, watchers.get(TEST_GROUP).size());
+    }
+
+    @Test
+    void testOnChangeEventWithTermMinus1() {
+        Watcher<AsyncContext> watcher =
+                new Watcher<>(TEST_GROUP, asyncContext, TEST_TIMEOUT, 
TEST_TERM, TEST_CLIENT_ENDPOINT);
+        clusterWatcherManager.registryWatcher(watcher);
+
+        ClusterChangeEvent minus1TermEvent = new ClusterChangeEvent(this, 
TEST_GROUP, -1);
+        clusterWatcherManager.onChangeEvent(minus1TermEvent);
+
+        Map<String, Long> updateTime =
+                (Map<String, Long>) 
ReflectionTestUtils.getField(clusterWatcherManager, "GROUP_UPDATE_TIME");
+        assertEquals(-1L, updateTime.get(TEST_GROUP));
+        Mockito.verify(response).setStatus(HttpServletResponse.SC_OK);
+        Mockito.verify(asyncContext).complete();
+        assertTrue(watcher.isDone());
+    }
 }
diff --git 
a/rm/src/test/java/org/apache/seata/rm/DefaultResourceManagerTest.java 
b/rm/src/test/java/org/apache/seata/rm/DefaultResourceManagerTest.java
new file mode 100644
index 0000000000..7612ed22ed
--- /dev/null
+++ b/rm/src/test/java/org/apache/seata/rm/DefaultResourceManagerTest.java
@@ -0,0 +1,355 @@
+/*
+ * 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.rm;
+
+import org.apache.seata.common.exception.FrameworkException;
+import org.apache.seata.common.loader.EnhancedServiceLoader;
+import org.apache.seata.core.exception.TransactionException;
+import org.apache.seata.core.model.BranchStatus;
+import org.apache.seata.core.model.BranchType;
+import org.apache.seata.core.model.GlobalStatus;
+import org.apache.seata.core.model.Resource;
+import org.apache.seata.core.model.ResourceManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Unit tests for DefaultResourceManager
+ */
+public class DefaultResourceManagerTest {
+
+    private DefaultResourceManager defaultRm;
+
+    @Mock
+    private ResourceManager mockAtRm;
+
+    @Mock
+    private ResourceManager mockTccRm;
+
+    @Mock
+    private Resource mockAtResource;
+
+    @Mock
+    private Resource mockTccResource;
+
+    private AutoCloseable closeable;
+
+    @BeforeEach
+    void setUp() {
+        closeable = MockitoAnnotations.openMocks(this);
+        defaultRm = DefaultResourceManager.get();
+        DefaultResourceManager.resourceManagers.clear();
+    }
+
+    @AfterEach
+    void tearDown() throws Exception {
+        closeable.close();
+        DefaultResourceManager.resourceManagers.clear();
+    }
+
+    @Test
+    void testGetInstanceIsSingleton() {
+        DefaultResourceManager instance1 = DefaultResourceManager.get();
+        DefaultResourceManager instance2 = DefaultResourceManager.get();
+        assertEquals(instance1, instance2);
+    }
+
+    @Test
+    void testInitResourceManagers() {
+        try (MockedStatic<EnhancedServiceLoader> mockedLoader = 
Mockito.mockStatic(EnhancedServiceLoader.class)) {
+            List<ResourceManager> rmList = new ArrayList<>();
+            rmList.add(mockAtRm);
+            rmList.add(mockTccRm);
+            
when(EnhancedServiceLoader.loadAll(ResourceManager.class)).thenReturn(rmList);
+            when(mockAtRm.getBranchType()).thenReturn(BranchType.AT);
+            when(mockTccRm.getBranchType()).thenReturn(BranchType.TCC);
+
+            // Re-initialize by creating new instance (using reflection for 
test)
+            DefaultResourceManager.resourceManagers.clear();
+            defaultRm.initResourceManagers();
+
+            assertEquals(2, DefaultResourceManager.resourceManagers.size());
+            assertEquals(mockAtRm, 
DefaultResourceManager.resourceManagers.get(BranchType.AT));
+            assertEquals(mockTccRm, 
DefaultResourceManager.resourceManagers.get(BranchType.TCC));
+        }
+    }
+
+    @Test
+    void testInitResourceManagersWithEmptyList() {
+        try (MockedStatic<EnhancedServiceLoader> mockedLoader = 
Mockito.mockStatic(EnhancedServiceLoader.class)) {
+            List<ResourceManager> emptyRmList = new ArrayList<>();
+            
when(EnhancedServiceLoader.loadAll(ResourceManager.class)).thenReturn(emptyRmList);
+
+            DefaultResourceManager.resourceManagers.clear();
+            defaultRm.initResourceManagers();
+
+            assertTrue(DefaultResourceManager.resourceManagers.isEmpty());
+        }
+    }
+
+    @Test
+    void testInitResourceManagersWithNullList() {
+        try (MockedStatic<EnhancedServiceLoader> mockedLoader = 
Mockito.mockStatic(EnhancedServiceLoader.class)) {
+            
when(EnhancedServiceLoader.loadAll(ResourceManager.class)).thenReturn(null);
+
+            DefaultResourceManager.resourceManagers.clear();
+            defaultRm.initResourceManagers();
+
+            assertTrue(DefaultResourceManager.resourceManagers.isEmpty());
+        }
+    }
+
+    @Test
+    void testMockResourceManager() {
+        DefaultResourceManager.mockResourceManager(BranchType.SAGA, mockAtRm);
+        assertEquals(mockAtRm, 
DefaultResourceManager.resourceManagers.get(BranchType.SAGA));
+    }
+
+    @Test
+    void testGetResourceManagerExistingType() {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        ResourceManager result = defaultRm.getResourceManager(BranchType.AT);
+        assertEquals(mockAtRm, result);
+    }
+
+    @Test
+    void testGetResourceManagerNonExistingType() {
+        FrameworkException exception =
+                assertThrows(FrameworkException.class, () -> 
defaultRm.getResourceManager(BranchType.XA));
+        assertTrue(exception.getMessage().contains("No ResourceManager for 
BranchType:XA"));
+    }
+
+    @Test
+    void testGetManagedResourcesWithPartialNullSubResources() {
+        when(mockAtRm.getManagedResources()).thenReturn(null);
+        Map<String, Resource> tccResources = new HashMap<>();
+        tccResources.put("tcc-res-1", mockTccResource);
+        when(mockTccRm.getManagedResources()).thenReturn(tccResources);
+
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+
+        Map<String, Resource> allResources = defaultRm.getManagedResources();
+        assertEquals(1, allResources.size());
+        assertTrue(allResources.containsKey("tcc-res-1"));
+        verify(mockAtRm).getManagedResources();
+        verify(mockTccRm).getManagedResources();
+    }
+
+    @Test
+    void testBranchCommit() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        when(mockAtRm.branchCommit(eq(BranchType.AT), eq("xid1"), eq(123L), 
eq("res1"), eq("data")))
+                .thenReturn(BranchStatus.PhaseTwo_Committed);
+
+        BranchStatus result = defaultRm.branchCommit(BranchType.AT, "xid1", 
123L, "res1", "data");
+        assertEquals(BranchStatus.PhaseTwo_Committed, result);
+        verify(mockAtRm).branchCommit(eq(BranchType.AT), eq("xid1"), eq(123L), 
eq("res1"), eq("data"));
+    }
+
+    @Test
+    void testBranchCommitWithUnderlyingTransactionException() throws 
TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        TransactionException expectedException = new 
TransactionException("Simulate underlying RM throws exception");
+        when(mockAtRm.branchCommit(
+                        eq(BranchType.AT), eq("xid-exception"), eq(999L), 
eq("res-exception"), eq("data-exception")))
+                .thenThrow(expectedException);
+
+        TransactionException actualException = assertThrows(
+                TransactionException.class,
+                () -> defaultRm.branchCommit(BranchType.AT, "xid-exception", 
999L, "res-exception", "data-exception"));
+
+        assertEquals(expectedException.getMessage(), 
actualException.getMessage());
+        verify(mockAtRm)
+                .branchCommit(
+                        eq(BranchType.AT), eq("xid-exception"), eq(999L), 
eq("res-exception"), eq("data-exception"));
+    }
+
+    @Test
+    void testBranchRollback() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+        when(mockTccRm.branchRollback(eq(BranchType.TCC), eq("xid2"), 
eq(456L), eq("res2"), eq("data2")))
+                .thenReturn(BranchStatus.PhaseTwo_Rollbacked);
+
+        BranchStatus result = defaultRm.branchRollback(BranchType.TCC, "xid2", 
456L, "res2", "data2");
+        assertEquals(BranchStatus.PhaseTwo_Rollbacked, result);
+        verify(mockTccRm).branchRollback(eq(BranchType.TCC), eq("xid2"), 
eq(456L), eq("res2"), eq("data2"));
+    }
+
+    @Test
+    void testBranchRegister() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        when(mockAtRm.branchRegister(
+                        eq(BranchType.AT), eq("res3"), eq("client1"), 
eq("xid3"), eq("data3"), eq("locks")))
+                .thenReturn(789L);
+
+        Long branchId = defaultRm.branchRegister(BranchType.AT, "res3", 
"client1", "xid3", "data3", "locks");
+        assertEquals(789L, branchId);
+        verify(mockAtRm)
+                .branchRegister(eq(BranchType.AT), eq("res3"), eq("client1"), 
eq("xid3"), eq("data3"), eq("locks"));
+    }
+
+    @Test
+    void testBranchReport() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+
+        defaultRm.branchReport(BranchType.TCC, "xid4", 101L, 
BranchStatus.PhaseOne_Done, "data4");
+        verify(mockTccRm)
+                .branchReport(eq(BranchType.TCC), eq("xid4"), eq(101L), 
eq(BranchStatus.PhaseOne_Done), eq("data4"));
+    }
+
+    @Test
+    void testBranchReportWithException() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+        TransactionException expectedException = new 
TransactionException("report failed");
+        Mockito.doThrow(expectedException)
+                .when(mockTccRm)
+                .branchReport(
+                        eq(BranchType.TCC), eq("xid-ex"), eq(222L), 
eq(BranchStatus.PhaseOne_Failed), eq("data-ex"));
+
+        TransactionException actualException = assertThrows(
+                TransactionException.class,
+                () -> defaultRm.branchReport(BranchType.TCC, "xid-ex", 222L, 
BranchStatus.PhaseOne_Failed, "data-ex"));
+
+        assertEquals(expectedException.getMessage(), 
actualException.getMessage());
+        verify(mockTccRm)
+                .branchReport(
+                        eq(BranchType.TCC), eq("xid-ex"), eq(222L), 
eq(BranchStatus.PhaseOne_Failed), eq("data-ex"));
+    }
+
+    @Test
+    void testLockQuery() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        when(mockAtRm.lockQuery(eq(BranchType.AT), eq("res5"), eq("xid5"), 
eq("locks5")))
+                .thenReturn(true);
+
+        boolean result = defaultRm.lockQuery(BranchType.AT, "res5", "xid5", 
"locks5");
+        assertTrue(result);
+        verify(mockAtRm).lockQuery(eq(BranchType.AT), eq("res5"), eq("xid5"), 
eq("locks5"));
+    }
+
+    @Test
+    void testLockQueryWithTransactionException() throws TransactionException {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        TransactionException expectedException = new 
TransactionException("lock query failed");
+        when(mockAtRm.lockQuery(eq(BranchType.AT), eq("res-ex"), eq("xid-ex"), 
eq("locks-ex")))
+                .thenThrow(expectedException);
+
+        TransactionException actualException = assertThrows(
+                TransactionException.class, () -> 
defaultRm.lockQuery(BranchType.AT, "res-ex", "xid-ex", "locks-ex"));
+
+        assertEquals(expectedException.getMessage(), 
actualException.getMessage());
+        verify(mockAtRm).lockQuery(eq(BranchType.AT), eq("res-ex"), 
eq("xid-ex"), eq("locks-ex"));
+    }
+
+    @Test
+    void testRegisterResource() {
+        when(mockAtResource.getBranchType()).thenReturn(BranchType.AT);
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+
+        defaultRm.registerResource(mockAtResource);
+        verify(mockAtRm).registerResource(mockAtResource);
+    }
+
+    @Test
+    void testRegisterResourceWithNonExistingBranchType() {
+        when(mockAtResource.getBranchType()).thenReturn(BranchType.XA);
+
+        FrameworkException exception =
+                assertThrows(FrameworkException.class, () -> 
defaultRm.registerResource(mockAtResource));
+        assertTrue(exception.getMessage().contains("No ResourceManager for 
BranchType:XA"));
+    }
+
+    @Test
+    void testUnregisterResource() {
+        when(mockTccResource.getBranchType()).thenReturn(BranchType.TCC);
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+
+        defaultRm.unregisterResource(mockTccResource);
+        verify(mockTccRm).unregisterResource(mockTccResource);
+    }
+
+    @Test
+    void testUnregisterResourceWithNonExistingBranchType() {
+        when(mockTccResource.getBranchType()).thenReturn(BranchType.XA);
+
+        FrameworkException exception =
+                assertThrows(FrameworkException.class, () -> 
defaultRm.unregisterResource(mockTccResource));
+        assertTrue(exception.getMessage().contains("No ResourceManager for 
BranchType:XA"));
+    }
+
+    @Test
+    void testGetManagedResources() {
+        Map<String, Resource> atResources = new HashMap<>();
+        atResources.put("resAt1", mockAtResource);
+        when(mockAtRm.getManagedResources()).thenReturn(atResources);
+
+        Map<String, Resource> tccResources = new HashMap<>();
+        tccResources.put("resTcc1", mockTccResource);
+        when(mockTccRm.getManagedResources()).thenReturn(tccResources);
+
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, mockTccRm);
+
+        Map<String, Resource> allResources = defaultRm.getManagedResources();
+        assertEquals(2, allResources.size());
+        assertTrue(allResources.containsKey("resAt1"));
+        assertTrue(allResources.containsKey("resTcc1"));
+    }
+
+    @Test
+    void testGetManagedResourcesWithEmptyResourceManagers() {
+        DefaultResourceManager.resourceManagers.clear();
+
+        Map<String, Resource> allResources = defaultRm.getManagedResources();
+
+        assertTrue(allResources.isEmpty());
+        assertEquals(HashMap.class, allResources.getClass());
+    }
+
+    @Test
+    void testGetBranchTypeThrowsException() {
+        assertThrows(FrameworkException.class, defaultRm::getBranchType);
+    }
+
+    @Test
+    void testGetGlobalStatus() {
+        DefaultResourceManager.mockResourceManager(BranchType.AT, mockAtRm);
+        when(mockAtRm.getGlobalStatus(eq(BranchType.AT), 
eq("xid6"))).thenReturn(GlobalStatus.Committed);
+
+        GlobalStatus status = defaultRm.getGlobalStatus(BranchType.AT, "xid6");
+        assertEquals(GlobalStatus.Committed, status);
+        verify(mockAtRm).getGlobalStatus(eq(BranchType.AT), eq("xid6"));
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to