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

maple 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 df3448f6bf test: add UT for XA module (#7776)
df3448f6bf is described below

commit df3448f6bfaf8fddca92262431b5586f1087725d
Author: maple <[email protected]>
AuthorDate: Fri Nov 21 15:42:58 2025 +0800

    test: add UT for XA module (#7776)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   3 +
 .../xa/AbstractConnectionProxyXATest.java          | 586 +++++++++++++++++++
 .../xa/AbstractDataSourceProxyXATest.java          | 239 ++++++++
 .../rm/datasource/xa/ConnectionProxyXATest.java    | 480 ++++++++++++++-
 .../rm/datasource/xa/ExecuteTemplateXATest.java    | 212 +++++++
 .../xa/PreparedStatementProxyXATest.java           | 648 +++++++++++++++++++++
 .../rm/datasource/xa/ResourceManagerXATest.java    | 354 +++++++++++
 .../rm/datasource/xa/StatementProxyXATest.java     | 567 ++++++++++++++++++
 9 files changed, 3075 insertions(+), 15 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index b54492d0e8..d27ede804c 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -107,6 +107,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7757](https://github.com/apache/incubator-seata/pull/7757)] add UT for 
undo module
 - [[#7763](https://github.com/apache/incubator-seata/pull/7763)] add UT for 
RegistryNamingServerProperties and RegistryMetadataProperties
 - [[#7764](https://github.com/apache/incubator-seata/pull/7764)] add some UT 
for server/coordinator module
+- [[#7776](https://github.com/apache/incubator-seata/pull/7776)] add UT for XA 
module
 - [[#7788](https://github.com/apache/incubator-seata/pull/7788)] add some UT 
for rm-datasource module
 - [[#7774](https://github.com/apache/incubator-seata/pull/7774)] add some UT 
for server/console module
 - [[#7767](https://github.com/apache/incubator-seata/pull/7767)] add some UT 
for server/cluster module
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 6b568db625..828ebd7de5 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -106,6 +106,7 @@
 - [[#7757](https://github.com/apache/incubator-seata/pull/7757)] 为 undo 模块添加单测
 - [[#7763](https://github.com/apache/incubator-seata/pull/7763)] 为 
RegistryNamingServerProperties 和 RegistryMetadataProperties 添加单测
 - [[#7764](https://github.com/apache/incubator-seata/pull/7764)] 为 
server/coordinator 模块添加单测
+- [[#7776](https://github.com/apache/incubator-seata/pull/7776)] 为 XA 模块添加单测
 - [[#7788](https://github.com/apache/incubator-seata/pull/7788)] 为 
rm-datasource 模块添加单测
 - [[#7774](https://github.com/apache/incubator-seata/pull/7774)] 为 
server/console 模块添加单测
 - [[#7767](https://github.com/apache/incubator-seata/pull/7767)] 为 
server/cluster 模块添加单测
@@ -113,6 +114,8 @@
 - [[#7733](https://github.com/apache/incubator-seata/pull/7733)] 为 core 模块添加单测
 - [[#7728](https://github.com/apache/incubator-seata/pull/7728)] 为 compatible 
模块添加单测
 - [[#7727](https://github.com/apache/incubator-seata/pull/7727)] 为 compatible 
模块添加单测
+
+
 ### refactor:
 
 - [[#7615](https://github.com/seata/seata/pull/7615)] 重构 DataSourceProxy
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractConnectionProxyXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractConnectionProxyXATest.java
new file mode 100644
index 0000000000..0ef24733c2
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractConnectionProxyXATest.java
@@ -0,0 +1,586 @@
+/*
+ * 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.datasource.xa;
+
+import org.apache.seata.rm.BaseDataSourceResource;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import javax.sql.XAConnection;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for AbstractConnectionProxyXA
+ *
+ */
+public class AbstractConnectionProxyXATest {
+
+    private Connection mockConnection;
+    private XAConnection mockXAConnection;
+    private BaseDataSourceResource mockResource;
+    private String xid;
+    private TestConnectionProxyXA connectionProxy;
+
+    @BeforeEach
+    public void setUp() throws SQLException {
+        mockConnection = mock(Connection.class);
+        mockXAConnection = mock(XAConnection.class);
+        mockResource = mock(BaseDataSourceResource.class);
+        xid = "testXid";
+
+        connectionProxy = new TestConnectionProxyXA(mockConnection, 
mockXAConnection, mockResource, xid);
+    }
+
+    @Test
+    public void testGetWrappedXAConnection() {
+        XAConnection result = connectionProxy.getWrappedXAConnection();
+        Assertions.assertEquals(mockXAConnection, result);
+    }
+
+    @Test
+    public void testGetWrappedConnection() {
+        Connection result = connectionProxy.getWrappedConnection();
+        Assertions.assertEquals(mockConnection, result);
+    }
+
+    @Test
+    public void testCreateStatement() throws SQLException {
+        Statement mockStatement = mock(Statement.class);
+        when(mockConnection.createStatement()).thenReturn(mockStatement);
+
+        Statement result = connectionProxy.createStatement();
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof StatementProxyXA);
+        verify(mockConnection).createStatement();
+    }
+
+    @Test
+    public void testCreateStatementWithParameters() throws SQLException {
+        Statement mockStatement = mock(Statement.class);
+        when(mockConnection.createStatement(anyInt(), 
anyInt())).thenReturn(mockStatement);
+
+        Statement result = connectionProxy.createStatement(1, 2);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof StatementProxyXA);
+        verify(mockConnection).createStatement(1, 2);
+    }
+
+    @Test
+    public void testCreateStatementWithThreeParameters() throws SQLException {
+        Statement mockStatement = mock(Statement.class);
+        when(mockConnection.createStatement(anyInt(), anyInt(), 
anyInt())).thenReturn(mockStatement);
+
+        Statement result = connectionProxy.createStatement(1, 2, 3);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof StatementProxyXA);
+        verify(mockConnection).createStatement(1, 2, 3);
+    }
+
+    @Test
+    public void testPrepareStatement() throws SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        
when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);
+
+        PreparedStatement result = connectionProxy.prepareStatement("SELECT * 
FROM test");
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("SELECT * FROM test");
+    }
+
+    @Test
+    public void testPrepareStatementWithParameters() throws SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        when(mockConnection.prepareStatement(anyString(), anyInt(), 
anyInt())).thenReturn(mockPreparedStatement);
+
+        PreparedStatement result = connectionProxy.prepareStatement("SELECT * 
FROM test", 1, 2);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("SELECT * FROM test", 1, 2);
+    }
+
+    @Test
+    public void testPrepareStatementWithThreeParameters() throws SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        when(mockConnection.prepareStatement(anyString(), anyInt(), anyInt(), 
anyInt()))
+                .thenReturn(mockPreparedStatement);
+
+        PreparedStatement result = connectionProxy.prepareStatement("SELECT * 
FROM test", 1, 2, 3);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("SELECT * FROM test", 1, 2, 3);
+    }
+
+    @Test
+    public void testPrepareStatementWithAutoGeneratedKeys() throws 
SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        when(mockConnection.prepareStatement(anyString(), 
anyInt())).thenReturn(mockPreparedStatement);
+
+        PreparedStatement result =
+                connectionProxy.prepareStatement("INSERT INTO test", 
Statement.RETURN_GENERATED_KEYS);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("INSERT INTO test", 
Statement.RETURN_GENERATED_KEYS);
+    }
+
+    @Test
+    public void testPrepareStatementWithColumnIndexes() throws SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        int[] columnIndexes = {1, 2};
+        when(mockConnection.prepareStatement(anyString(), 
any(int[].class))).thenReturn(mockPreparedStatement);
+
+        PreparedStatement result = connectionProxy.prepareStatement("INSERT 
INTO test", columnIndexes);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("INSERT INTO test", 
columnIndexes);
+    }
+
+    @Test
+    public void testPrepareStatementWithColumnNames() throws SQLException {
+        PreparedStatement mockPreparedStatement = 
mock(PreparedStatement.class);
+        String[] columnNames = {"id", "name"};
+        when(mockConnection.prepareStatement(anyString(), 
any(String[].class))).thenReturn(mockPreparedStatement);
+
+        PreparedStatement result = connectionProxy.prepareStatement("INSERT 
INTO test", columnNames);
+
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof PreparedStatementProxyXA);
+        verify(mockConnection).prepareStatement("INSERT INTO test", 
columnNames);
+    }
+
+    @Test
+    public void testNativeSQL() throws SQLException {
+        String sql = "SELECT * FROM test";
+        String nativeSQL = "SELECT * FROM test_native";
+        when(mockConnection.nativeSQL(sql)).thenReturn(nativeSQL);
+
+        String result = connectionProxy.nativeSQL(sql);
+
+        Assertions.assertEquals(nativeSQL, result);
+        verify(mockConnection).nativeSQL(sql);
+    }
+
+    @Test
+    public void testIsClosed() throws SQLException {
+        when(mockConnection.isClosed()).thenReturn(false);
+
+        boolean result = connectionProxy.isClosed();
+
+        Assertions.assertFalse(result);
+        verify(mockConnection).isClosed();
+    }
+
+    @Test
+    public void testGetMetaData() throws SQLException {
+        DatabaseMetaData mockMetaData = mock(DatabaseMetaData.class);
+        when(mockConnection.getMetaData()).thenReturn(mockMetaData);
+
+        DatabaseMetaData result = connectionProxy.getMetaData();
+
+        Assertions.assertEquals(mockMetaData, result);
+        verify(mockConnection).getMetaData();
+    }
+
+    @Test
+    public void testSetReadOnly() throws SQLException {
+        connectionProxy.setReadOnly(true);
+
+        verify(mockConnection).setReadOnly(true);
+    }
+
+    @Test
+    public void testIsReadOnly() throws SQLException {
+        when(mockConnection.isReadOnly()).thenReturn(true);
+
+        boolean result = connectionProxy.isReadOnly();
+
+        Assertions.assertTrue(result);
+        verify(mockConnection).isReadOnly();
+    }
+
+    @Test
+    public void testSetCatalog() throws SQLException {
+        String catalog = "testCatalog";
+        connectionProxy.setCatalog(catalog);
+
+        verify(mockConnection).setCatalog(catalog);
+    }
+
+    @Test
+    public void testGetCatalog() throws SQLException {
+        String catalog = "testCatalog";
+        when(mockConnection.getCatalog()).thenReturn(catalog);
+
+        String result = connectionProxy.getCatalog();
+
+        Assertions.assertEquals(catalog, result);
+        verify(mockConnection).getCatalog();
+    }
+
+    @Test
+    public void testSetTransactionIsolation() throws SQLException {
+        
connectionProxy.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+
+        
verify(mockConnection).setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+    }
+
+    @Test
+    public void testGetTransactionIsolation() throws SQLException {
+        
when(mockConnection.getTransactionIsolation()).thenReturn(Connection.TRANSACTION_READ_COMMITTED);
+
+        int result = connectionProxy.getTransactionIsolation();
+
+        Assertions.assertEquals(Connection.TRANSACTION_READ_COMMITTED, result);
+        verify(mockConnection).getTransactionIsolation();
+    }
+
+    @Test
+    public void testGetWarnings() throws SQLException {
+        SQLWarning mockWarning = mock(SQLWarning.class);
+        when(mockConnection.getWarnings()).thenReturn(mockWarning);
+
+        SQLWarning result = connectionProxy.getWarnings();
+
+        Assertions.assertEquals(mockWarning, result);
+        verify(mockConnection).getWarnings();
+    }
+
+    @Test
+    public void testClearWarnings() throws SQLException {
+        connectionProxy.clearWarnings();
+
+        verify(mockConnection).clearWarnings();
+    }
+
+    @Test
+    public void testGetTypeMap() throws SQLException {
+        Map<String, Class<?>> typeMap = new HashMap<>();
+        when(mockConnection.getTypeMap()).thenReturn(typeMap);
+
+        Map<String, Class<?>> result = connectionProxy.getTypeMap();
+
+        Assertions.assertEquals(typeMap, result);
+        verify(mockConnection).getTypeMap();
+    }
+
+    @Test
+    public void testSetTypeMap() throws SQLException {
+        Map<String, Class<?>> typeMap = new HashMap<>();
+        connectionProxy.setTypeMap(typeMap);
+
+        verify(mockConnection).setTypeMap(typeMap);
+    }
+
+    @Test
+    public void testSetHoldability() throws SQLException {
+        connectionProxy.setHoldability(1);
+
+        verify(mockConnection).setHoldability(1);
+    }
+
+    @Test
+    public void testGetHoldability() throws SQLException {
+        when(mockConnection.getHoldability()).thenReturn(1);
+
+        int result = connectionProxy.getHoldability();
+
+        Assertions.assertEquals(1, result);
+        verify(mockConnection).getHoldability();
+    }
+
+    @Test
+    public void testSetSavepoint() throws SQLException {
+        Savepoint mockSavepoint = mock(Savepoint.class);
+        when(mockConnection.setSavepoint()).thenReturn(mockSavepoint);
+
+        Savepoint result = connectionProxy.setSavepoint();
+
+        Assertions.assertEquals(mockSavepoint, result);
+        verify(mockConnection).setSavepoint();
+    }
+
+    @Test
+    public void testSetSavepointWithName() throws SQLException {
+        Savepoint mockSavepoint = mock(Savepoint.class);
+        when(mockConnection.setSavepoint("sp1")).thenReturn(mockSavepoint);
+
+        Savepoint result = connectionProxy.setSavepoint("sp1");
+
+        Assertions.assertEquals(mockSavepoint, result);
+        verify(mockConnection).setSavepoint("sp1");
+    }
+
+    @Test
+    public void testRollbackSavepoint() throws SQLException {
+        Savepoint mockSavepoint = mock(Savepoint.class);
+        connectionProxy.rollback(mockSavepoint);
+
+        verify(mockConnection).rollback(mockSavepoint);
+    }
+
+    @Test
+    public void testReleaseSavepoint() throws SQLException {
+        Savepoint mockSavepoint = mock(Savepoint.class);
+        connectionProxy.releaseSavepoint(mockSavepoint);
+
+        verify(mockConnection).releaseSavepoint(mockSavepoint);
+    }
+
+    @Test
+    public void testCreateClob() throws SQLException {
+        Clob mockClob = mock(Clob.class);
+        when(mockConnection.createClob()).thenReturn(mockClob);
+
+        Clob result = connectionProxy.createClob();
+
+        Assertions.assertEquals(mockClob, result);
+        verify(mockConnection).createClob();
+    }
+
+    @Test
+    public void testCreateBlob() throws SQLException {
+        Blob mockBlob = mock(Blob.class);
+        when(mockConnection.createBlob()).thenReturn(mockBlob);
+
+        Blob result = connectionProxy.createBlob();
+
+        Assertions.assertEquals(mockBlob, result);
+        verify(mockConnection).createBlob();
+    }
+
+    @Test
+    public void testCreateNClob() throws SQLException {
+        NClob mockNClob = mock(NClob.class);
+        when(mockConnection.createNClob()).thenReturn(mockNClob);
+
+        NClob result = connectionProxy.createNClob();
+
+        Assertions.assertEquals(mockNClob, result);
+        verify(mockConnection).createNClob();
+    }
+
+    @Test
+    public void testCreateSQLXML() throws SQLException {
+        SQLXML mockSQLXML = mock(SQLXML.class);
+        when(mockConnection.createSQLXML()).thenReturn(mockSQLXML);
+
+        SQLXML result = connectionProxy.createSQLXML();
+
+        Assertions.assertEquals(mockSQLXML, result);
+        verify(mockConnection).createSQLXML();
+    }
+
+    @Test
+    public void testIsValid() throws SQLException {
+        when(mockConnection.isValid(10)).thenReturn(true);
+
+        boolean result = connectionProxy.isValid(10);
+
+        Assertions.assertTrue(result);
+        verify(mockConnection).isValid(10);
+    }
+
+    @Test
+    public void testSetClientInfo() throws SQLClientInfoException {
+        connectionProxy.setClientInfo("name", "value");
+
+        verify(mockConnection).setClientInfo("name", "value");
+    }
+
+    @Test
+    public void testSetClientInfoWithProperties() throws 
SQLClientInfoException {
+        Properties properties = new Properties();
+        connectionProxy.setClientInfo(properties);
+
+        verify(mockConnection).setClientInfo(properties);
+    }
+
+    @Test
+    public void testGetClientInfo() throws SQLException {
+        when(mockConnection.getClientInfo("name")).thenReturn("value");
+
+        String result = connectionProxy.getClientInfo("name");
+
+        Assertions.assertEquals("value", result);
+        verify(mockConnection).getClientInfo("name");
+    }
+
+    @Test
+    public void testGetClientInfoProperties() throws SQLException {
+        Properties properties = new Properties();
+        when(mockConnection.getClientInfo()).thenReturn(properties);
+
+        Properties result = connectionProxy.getClientInfo();
+
+        Assertions.assertEquals(properties, result);
+        verify(mockConnection).getClientInfo();
+    }
+
+    @Test
+    public void testCreateArrayOf() throws SQLException {
+        Array mockArray = mock(Array.class);
+        Object[] elements = {"a", "b"};
+        when(mockConnection.createArrayOf("VARCHAR", 
elements)).thenReturn(mockArray);
+
+        Array result = connectionProxy.createArrayOf("VARCHAR", elements);
+
+        Assertions.assertEquals(mockArray, result);
+        verify(mockConnection).createArrayOf("VARCHAR", elements);
+    }
+
+    @Test
+    public void testCreateStruct() throws SQLException {
+        Struct mockStruct = mock(Struct.class);
+        Object[] attributes = {1, "test"};
+        when(mockConnection.createStruct("TYPE", 
attributes)).thenReturn(mockStruct);
+
+        Struct result = connectionProxy.createStruct("TYPE", attributes);
+
+        Assertions.assertEquals(mockStruct, result);
+        verify(mockConnection).createStruct("TYPE", attributes);
+    }
+
+    @Test
+    public void testSetSchema() throws SQLException {
+        connectionProxy.setSchema("testSchema");
+
+        verify(mockConnection).setSchema("testSchema");
+    }
+
+    @Test
+    public void testGetSchema() throws SQLException {
+        when(mockConnection.getSchema()).thenReturn("testSchema");
+
+        String result = connectionProxy.getSchema();
+
+        Assertions.assertEquals("testSchema", result);
+        verify(mockConnection).getSchema();
+    }
+
+    @Test
+    public void testAbort() throws SQLException {
+        Executor mockExecutor = mock(Executor.class);
+        connectionProxy.abort(mockExecutor);
+
+        verify(mockConnection).abort(mockExecutor);
+    }
+
+    @Test
+    public void testSetNetworkTimeout() throws SQLException {
+        Executor mockExecutor = mock(Executor.class);
+        connectionProxy.setNetworkTimeout(mockExecutor, 1000);
+
+        verify(mockConnection).setNetworkTimeout(mockExecutor, 1000);
+    }
+
+    @Test
+    public void testGetNetworkTimeout() throws SQLException {
+        when(mockConnection.getNetworkTimeout()).thenReturn(1000);
+
+        int result = connectionProxy.getNetworkTimeout();
+
+        Assertions.assertEquals(1000, result);
+        verify(mockConnection).getNetworkTimeout();
+    }
+
+    @Test
+    public void testUnwrap() throws SQLException {
+        
when(mockConnection.unwrap(Connection.class)).thenReturn(mockConnection);
+
+        Connection result = connectionProxy.unwrap(Connection.class);
+
+        Assertions.assertEquals(mockConnection, result);
+        verify(mockConnection).unwrap(Connection.class);
+    }
+
+    @Test
+    public void testIsWrapperFor() throws SQLException {
+        when(mockConnection.isWrapperFor(Connection.class)).thenReturn(true);
+
+        boolean result = connectionProxy.isWrapperFor(Connection.class);
+
+        Assertions.assertTrue(result);
+        verify(mockConnection).isWrapperFor(Connection.class);
+    }
+
+    /**
+     * Test implementation of AbstractConnectionProxyXA for testing purposes
+     */
+    private static class TestConnectionProxyXA extends 
AbstractConnectionProxyXA {
+        public TestConnectionProxyXA(
+                Connection originalConnection, XAConnection xaConnection, 
BaseDataSourceResource resource, String xid) {
+            super(originalConnection, xaConnection, resource, xid);
+        }
+
+        @Override
+        public void setAutoCommit(boolean autoCommit) throws SQLException {
+            // Test implementation
+        }
+
+        @Override
+        public boolean getAutoCommit() throws SQLException {
+            return false;
+        }
+
+        @Override
+        public void commit() throws SQLException {
+            // Test implementation
+        }
+
+        @Override
+        public void rollback() throws SQLException {
+            // Test implementation
+        }
+
+        @Override
+        public void close() throws SQLException {
+            // Test implementation
+        }
+    }
+}
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractDataSourceProxyXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractDataSourceProxyXATest.java
new file mode 100644
index 0000000000..2f384cffcb
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/AbstractDataSourceProxyXATest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.datasource.xa;
+
+import org.apache.seata.core.model.BranchType;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import javax.sql.PooledConnection;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for AbstractDataSourceProxyXA
+ * Focus on verifying actual results and business logic
+ */
+public class AbstractDataSourceProxyXATest {
+
+    private TestDataSourceProxyXA dataSourceProxy;
+    private XAXid xaXid;
+
+    @BeforeEach
+    public void setUp() {
+        dataSourceProxy = new TestDataSourceProxyXA();
+        xaXid = XAXidBuilder.build("testXid", 123L);
+    }
+
+    @Test
+    public void testGetConnectionForXAFinish_ReturnsExistingOpenConnection() 
throws SQLException {
+        // Verify that an existing open connection is returned (not a new one)
+        ConnectionProxyXA existingConnection = mock(ConnectionProxyXA.class);
+        Connection mockWrappedConnection = mock(Connection.class);
+        
when(existingConnection.getWrappedConnection()).thenReturn(mockWrappedConnection);
+        when(mockWrappedConnection.isClosed()).thenReturn(false);
+
+        // Store the existing connection
+        dataSourceProxy.hold(xaXid.toString(), existingConnection);
+
+        // Get connection for XA finish
+        ConnectionProxyXA result = 
dataSourceProxy.getConnectionForXAFinish(xaXid);
+
+        // Verify it returns the EXACT same connection instance (not a new one)
+        Assertions.assertSame(
+                existingConnection, result, "Should return the exact same 
connection instance that was held");
+
+        // Verify that getConnectionProxyXA was NOT called (didn't create a 
new connection)
+        Assertions.assertEquals(
+                0,
+                dataSourceProxy.getConnectionProxyXACallCount,
+                "Should not create a new connection when an open one exists");
+    }
+
+    @Test
+    public void 
testGetConnectionForXAFinish_CreatesNewConnectionWhenExistingIsClosed() throws 
SQLException {
+        // Verify that a new connection is created when the existing one is 
closed
+        ConnectionProxyXA closedConnection = mock(ConnectionProxyXA.class);
+        Connection mockWrappedConnection = mock(Connection.class);
+        
when(closedConnection.getWrappedConnection()).thenReturn(mockWrappedConnection);
+        when(mockWrappedConnection.isClosed()).thenReturn(true);
+
+        // Store the closed connection
+        dataSourceProxy.hold(xaXid.toString(), closedConnection);
+
+        // Get connection for XA finish
+        ConnectionProxyXA result = 
dataSourceProxy.getConnectionForXAFinish(xaXid);
+
+        // Verify it returns the NEW connection (from getConnectionProxyXA)
+        Assertions.assertSame(
+                dataSourceProxy.getNewConnection(),
+                result,
+                "Should return a new connection when existing one is closed");
+
+        // Verify that a new connection was actually created
+        Assertions.assertEquals(
+                1, dataSourceProxy.getConnectionProxyXACallCount, "Should 
create exactly one new connection");
+    }
+
+    @Test
+    public void 
testGetConnectionForXAFinish_CreatesNewConnectionWhenNoneExists() throws 
SQLException {
+        // Verify that a new connection is created when no existing connection 
is found
+
+        // Don't hold any connection, so lookup returns null
+        ConnectionProxyXA result = 
dataSourceProxy.getConnectionForXAFinish(xaXid);
+
+        // Verify it returns the new connection from getConnectionProxyXA
+        Assertions.assertSame(
+                dataSourceProxy.getNewConnection(),
+                result,
+                "Should return a new connection when no existing connection is 
found");
+
+        // Verify that a new connection was actually created
+        Assertions.assertEquals(
+                1, dataSourceProxy.getConnectionProxyXACallCount, "Should 
create exactly one new connection");
+    }
+
+    @Test
+    public void 
testForceClosePhysicalConnection_ClosesConnectionAndWrappedConnection() throws 
SQLException {
+        // Verify that both the connection proxy and its wrapped connection 
are closed
+        ConnectionProxyXA mockConnection = mock(ConnectionProxyXA.class);
+        Connection mockWrappedConnection = mock(Connection.class);
+
+        Mockito.doNothing().when(mockConnection).close();
+        
when(mockConnection.getWrappedConnection()).thenReturn(mockWrappedConnection);
+        Mockito.doNothing().when(mockWrappedConnection).close();
+
+        // Store the connection
+        dataSourceProxy.hold(xaXid.toString(), mockConnection);
+
+        // Force close
+        dataSourceProxy.forceClosePhysicalConnection(xaXid);
+
+        // Verify both connections were closed
+        verify(mockConnection).close();
+        verify(mockWrappedConnection).close();
+    }
+
+    @Test
+    public void 
testForceClosePhysicalConnection_ClosesPooledConnectionCorrectly() throws 
SQLException {
+        // Verify that for PooledConnection, the physical connection is closed
+        Connection mockWrappedConnection =
+                mock(Connection.class, 
Mockito.withSettings().extraInterfaces(PooledConnection.class));
+        Connection mockPhysicalConnection = mock(Connection.class);
+
+        ConnectionProxyXA mockConnection = mock(ConnectionProxyXA.class);
+
+        Mockito.doNothing().when(mockConnection).close();
+        
when(mockConnection.getWrappedConnection()).thenReturn(mockWrappedConnection);
+        when(((PooledConnection) 
mockWrappedConnection).getConnection()).thenReturn(mockPhysicalConnection);
+        Mockito.doNothing().when(mockPhysicalConnection).close();
+
+        // Store the connection
+        dataSourceProxy.hold(xaXid.toString(), mockConnection);
+
+        // Force close
+        dataSourceProxy.forceClosePhysicalConnection(xaXid);
+
+        // Verify the proxy connection was closed
+        verify(mockConnection).close();
+
+        // Verify the physical connection (from PooledConnection) was closed, 
not the wrapper
+        verify(mockPhysicalConnection).close();
+        verify(mockWrappedConnection, never()).close();
+    }
+
+    @Test
+    public void testForceClosePhysicalConnection_DoesNothingWhenNoConnection() 
throws SQLException {
+        // Verify that no exception is thrown when there's no connection to 
close
+
+        // Don't hold any connection
+        Assertions.assertDoesNotThrow(
+                () -> dataSourceProxy.forceClosePhysicalConnection(xaXid),
+                "Should not throw exception when no connection exists");
+
+        // Verify no connections were created or closed
+        Assertions.assertEquals(0, 
dataSourceProxy.getConnectionProxyXACallCount, "Should not create any 
connections");
+    }
+
+    @Test
+    public void testDefaultResourceGroupId() {
+        // Verify the default resource group ID constant value
+        Assertions.assertEquals(
+                "DEFAULT_XA",
+                TestDataSourceProxyXA.DEFAULT_RESOURCE_GROUP_ID,
+                "DEFAULT_RESOURCE_GROUP_ID should be 'DEFAULT_XA'");
+    }
+
+    @Test
+    public void testGetBranchType() {
+        // Verify getBranchType returns the correct branch type
+        Assertions.assertEquals(BranchType.XA, 
dataSourceProxy.getBranchType(), "Branch type should be XA");
+    }
+
+    @Test
+    public void testGetResourceId() {
+        // Verify getResourceId returns the configured resource ID
+        Assertions.assertEquals(
+                "test-resource-id", dataSourceProxy.getResourceId(), "Resource 
ID should match the configured value");
+    }
+
+    /**
+     * Test implementation of AbstractDataSourceProxyXA for testing purposes
+     */
+    private static class TestDataSourceProxyXA extends 
AbstractDataSourceProxyXA {
+
+        private ConnectionProxyXA mockConnectionProxy;
+        int getConnectionProxyXACallCount = 0;
+
+        public TestDataSourceProxyXA() {
+            this.branchType = BranchType.XA;
+            this.resourceId = "test-resource-id";
+        }
+
+        @Override
+        protected Connection getConnectionProxyXA() throws SQLException {
+            getConnectionProxyXACallCount++;
+            // Create a new mock connection each time
+            mockConnectionProxy = mock(ConnectionProxyXA.class);
+            Connection mockWrappedConnection = mock(Connection.class);
+            
when(mockConnectionProxy.getWrappedConnection()).thenReturn(mockWrappedConnection);
+            when(mockWrappedConnection.isClosed()).thenReturn(false);
+            return mockConnectionProxy;
+        }
+
+        public ConnectionProxyXA getNewConnection() {
+            return mockConnectionProxy;
+        }
+
+        @Override
+        public Connection getConnection() throws SQLException {
+            return getConnectionProxyXA();
+        }
+
+        @Override
+        public Connection getConnection(String username, String password) 
throws SQLException {
+            return getConnectionProxyXA();
+        }
+    }
+}
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java
index 9efad1a81a..e1f451986c 100644
--- 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java
@@ -16,7 +16,10 @@
  */
 package org.apache.seata.rm.datasource.xa;
 
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.core.context.RootContext;
+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.Resource;
 import org.apache.seata.core.model.ResourceManager;
@@ -24,17 +27,28 @@ import org.apache.seata.rm.BaseDataSourceResource;
 import org.apache.seata.rm.DefaultResourceManager;
 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.Mockito;
 
 import javax.sql.XAConnection;
+import javax.transaction.xa.XAException;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.Xid;
 import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
 import java.sql.Statement;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
 
 /**
  * Tests for ConnectionProxyXA
@@ -42,16 +56,72 @@ import static org.mockito.Mockito.times;
  */
 public class ConnectionProxyXATest {
 
+    private Connection mockConnection;
+    private XAConnection mockXAConnection;
+    private XAResource mockXAResource;
+    private BaseDataSourceResource<ConnectionProxyXA> mockDataSourceResource;
+    private ResourceManager mockResourceManager;
+
+    @BeforeEach
+    public void setUp() throws SQLException, XAException {
+        mockConnection = Mockito.mock(Connection.class);
+        mockXAConnection = Mockito.mock(XAConnection.class);
+        mockXAResource = Mockito.mock(XAResource.class);
+        mockDataSourceResource = Mockito.mock(BaseDataSourceResource.class);
+        mockResourceManager = Mockito.mock(ResourceManager.class);
+
+        // Default setup
+        when(mockConnection.getAutoCommit()).thenReturn(true);
+        when(mockXAConnection.getXAResource()).thenReturn(mockXAResource);
+        
Mockito.doNothing().when(mockResourceManager).registerResource(any(Resource.class));
+
+        DefaultResourceManager.get();
+        DefaultResourceManager.mockResourceManager(BranchType.XA, 
mockResourceManager);
+    }
+
     @Test
-    public void testInit() throws Throwable {
-        Connection connection = Mockito.mock(Connection.class);
-        Mockito.when(connection.getAutoCommit()).thenReturn(false);
-        XAConnection xaConnection = Mockito.mock(XAConnection.class);
-        BaseDataSourceResource<ConnectionProxyXA> baseDataSourceResource = 
Mockito.mock(BaseDataSourceResource.class);
-        String xid = "xxx";
+    public void testConstructor() {
+        // Test constructor properly initializes the proxy
+        String xid = "test-xid-123";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        Assertions.assertNotNull(connectionProxyXA, "Constructor should create 
a valid proxy instance");
+
+        // Verify that the proxy correctly wraps the provided connections
+        Assertions.assertSame(
+                mockConnection,
+                connectionProxyXA.getWrappedConnection(),
+                "Should correctly wrap the original connection");
+        Assertions.assertSame(
+                mockXAConnection,
+                connectionProxyXA.getWrappedXAConnection(),
+                "Should correctly wrap the XA connection");
+    }
+
+    @Test
+    public void testInitSuccess() throws SQLException {
+        // Test successful initialization
+        String xid = "test-xid-success";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        // This should succeed without throwing an exception
+        Assertions.assertDoesNotThrow(() -> connectionProxyXA.init(), "Init 
should succeed when autocommit=true");
+
+        // Verify the connection's autocommit status was checked
+        Mockito.verify(mockConnection).getAutoCommit();
+        Mockito.verify(mockXAConnection).getXAResource();
+    }
+
+    @Test
+    public void testInitFailsWithAutoCommitFalse() throws SQLException {
+        // Test initialization failure when autocommit is false
+        when(mockConnection.getAutoCommit()).thenReturn(false);
+        String xid = "test-xid-fail";
 
         ConnectionProxyXA connectionProxyXA =
-                new ConnectionProxyXA(connection, xaConnection, 
baseDataSourceResource, xid);
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
 
         Assertions.assertThrows(
                 IllegalStateException.class,
@@ -59,6 +129,21 @@ public class ConnectionProxyXATest {
                 "Connection[autocommit=false] as default is NOT supported");
     }
 
+    @Test
+    public void testInitFailsWithSQLException() throws SQLException {
+        // Test initialization failure when SQLException is thrown
+        when(mockConnection.getAutoCommit()).thenThrow(new 
SQLException("Connection error"));
+        String xid = "test-xid-sql-error";
+
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        Assertions.assertThrows(
+                RuntimeException.class,
+                connectionProxyXA::init,
+                "Init should throw RuntimeException when SQLException occurs");
+    }
+
     @Test
     public void testXABranchCommit() throws Throwable {
         Connection connection = Mockito.mock(Connection.class);
@@ -83,11 +168,11 @@ public class ConnectionProxyXATest {
         // Assert setAutoCommit = false was NEVER invoked on the wrapped 
connection
         Mockito.verify(connection, times(0)).setAutoCommit(false);
         // Assert XA start was invoked
-        Mockito.verify(xaResource).start(any(Xid.class), any(Integer.class));
+        Mockito.verify(xaResource).start(any(Xid.class), anyInt());
 
         connectionProxyXA.commit();
 
-        Mockito.verify(xaResource, times(0)).end(any(Xid.class), 
any(Integer.class));
+        Mockito.verify(xaResource, times(0)).end(any(Xid.class), anyInt());
         Mockito.verify(xaResource, times(0)).prepare(any(Xid.class));
     }
 
@@ -116,11 +201,11 @@ public class ConnectionProxyXATest {
         Mockito.verify(connection, times(0)).setAutoCommit(false);
 
         // Assert XA start was invoked
-        Mockito.verify(xaResource).start(any(Xid.class), any(Integer.class));
+        Mockito.verify(xaResource).start(any(Xid.class), anyInt());
 
         connectionProxyXA.rollback();
 
-        Mockito.verify(xaResource).end(any(Xid.class), any(Integer.class));
+        Mockito.verify(xaResource).end(any(Xid.class), anyInt());
 
         // Not prepared
         Mockito.verify(xaResource, times(0)).prepare(any(Xid.class));
@@ -173,7 +258,7 @@ public class ConnectionProxyXATest {
 
         connectionProxyXA.xaCommit("xxx", 123L, null);
 
-        Mockito.verify(xaResource).commit(any(Xid.class), any(Boolean.class));
+        Mockito.verify(xaResource).commit(any(Xid.class), anyBoolean());
         Mockito.verify(xaResource, times(0)).rollback(any(Xid.class));
     }
 
@@ -195,7 +280,7 @@ public class ConnectionProxyXATest {
 
         connectionProxyXA.xaRollback("xxx", 123L, null);
 
-        Mockito.verify(xaResource, times(0)).commit(any(Xid.class), 
any(Boolean.class));
+        Mockito.verify(xaResource, times(0)).commit(any(Xid.class), 
anyBoolean());
         Mockito.verify(xaResource).rollback(any(Xid.class));
     }
 
@@ -237,17 +322,382 @@ public class ConnectionProxyXATest {
         // Assert setAutoCommit = false was NEVER invoked on the wrapped 
connection
         Mockito.verify(connection, times(0)).setAutoCommit(false);
         // Assert XA start was invoked
-        Mockito.verify(xaResource, times(0)).start(any(Xid.class), 
any(Integer.class));
+        Mockito.verify(xaResource, times(0)).start(any(Xid.class), anyInt());
 
         connectionProxyXA.commit();
 
-        Mockito.verify(xaResource, times(0)).end(any(Xid.class), 
any(Integer.class));
+        Mockito.verify(xaResource, times(0)).end(any(Xid.class), anyInt());
         Mockito.verify(xaResource, times(0)).prepare(any(Xid.class));
 
         connectionProxyXA.rollback();
         Mockito.verify(xaResource, times(0)).rollback(any(Xid.class));
     }
 
+    @Test
+    public void testGetAutoCommit() throws SQLException, TransactionException {
+        // Test getAutoCommit returns current status
+        String xid = "test-autocommit";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Initial state should be true (from setUp)
+        Assertions.assertTrue(connectionProxyXA.getAutoCommit(), 
"getAutoCommit should return true initially");
+
+        // After setting autocommit to false, it should return false
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-autocommit"), eq(null), eq(null)))
+                .thenReturn(123L);
+        connectionProxyXA.setAutoCommit(false);
+        Assertions.assertFalse(
+                connectionProxyXA.getAutoCommit(), "getAutoCommit should 
return false after setAutoCommit(false)");
+    }
+
+    @Test
+    public void testSetAutoCommitFromTrueToFalse() throws Exception {
+        // Test setting autocommit from true to false (starting XA transaction)
+        String xid = "test-xa-start";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-xa-start"), eq(null), eq(null)))
+                .thenReturn(123L);
+
+        connectionProxyXA.setAutoCommit(false);
+
+        // Verify XA start was called
+        Mockito.verify(mockXAResource).start(any(Xid.class), 
eq(XAResource.TMNOFLAGS));
+        // Parameters: BranchType.XA, resource.getResourceId(), null, xid, 
null, null
+        Mockito.verify(mockResourceManager)
+                .branchRegister(eq(BranchType.XA), eq(null), eq(null), 
eq("test-xa-start"), eq(null), eq(null));
+
+        Assertions.assertFalse(connectionProxyXA.getAutoCommit(), "AutoCommit 
should be false");
+    }
+
+    @Test
+    public void testSetAutoCommitFromFalseToTrue() throws Exception {
+        // Test setting autocommit from false to true (committing XA 
transaction)
+        String xid = "test-xa-commit";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-xa-commit"), eq(null), eq(null)))
+                .thenReturn(123L);
+
+        // First set to false to start XA
+        connectionProxyXA.setAutoCommit(false);
+        // Then set back to true to commit
+        connectionProxyXA.setAutoCommit(true);
+
+        Assertions.assertTrue(connectionProxyXA.getAutoCommit(), "AutoCommit 
should be true");
+    }
+
+    @Test
+    public void testSetAutoCommitSameValue() throws SQLException, XAException, 
TransactionException {
+        // Test setting autocommit to the same value (should be no-op)
+        String xid = "test-same-value";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Set to true (already true, should be no-op)
+        connectionProxyXA.setAutoCommit(true);
+
+        // Verify no XA operations were performed
+        Mockito.verify(mockXAResource, times(0)).start(any(Xid.class), 
anyInt());
+        Mockito.verify(mockResourceManager, times(0))
+                .branchRegister(eq(BranchType.XA), anyString(), eq(null), 
anyString(), eq(null), eq(null));
+    }
+
+    @Test
+    public void testSetAutoCommitOnReadOnlyTransaction() throws SQLException, 
XAException {
+        // Test setAutoCommit on read-only transaction
+        when(mockConnection.isReadOnly()).thenReturn(true);
+        String xid = "test-readonly";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        connectionProxyXA.setAutoCommit(false);
+
+        // Verify no XA operations were performed for read-only transaction
+        Mockito.verify(mockXAResource, times(0)).start(any(Xid.class), 
anyInt());
+        Assertions.assertFalse(connectionProxyXA.getAutoCommit(), "AutoCommit 
should be false");
+    }
+
+    @Test
+    public void testSetAutoCommitXAStartFails() throws Exception {
+        // Test setAutoCommit when XA start fails
+        String xid = "test-xa-start-fail";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-xa-start-fail"), eq(null), eq(null)))
+                .thenReturn(123L);
+        doThrow(new XAException("XA start 
failed")).when(mockXAResource).start(any(Xid.class), anyInt());
+
+        SQLException exception = Assertions.assertThrows(
+                SQLException.class,
+                () -> connectionProxyXA.setAutoCommit(false),
+                "Should throw SQLException when XA start fails");
+
+        Assertions.assertTrue(
+                exception.getMessage().contains("failed to start xa branch"),
+                "Exception message should indicate XA start failure");
+    }
+
+    @Test
+    public void testCommitOnAutoCommitSession() throws SQLException, 
XAException {
+        // Test commit on autocommit session (should be ignored)
+        String xid = "test-commit-autocommit";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Should not throw exception and should be ignored
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.commit(), "Commit on autocommit 
session should be ignored");
+
+        // Verify no XA operations
+        Mockito.verify(mockXAResource, times(0)).end(any(Xid.class), anyInt());
+        Mockito.verify(mockXAResource, times(0)).prepare(any(Xid.class));
+    }
+
+    @Test
+    public void testCommitOnReadOnlyTransaction() throws Exception {
+        // Test commit on read-only transaction
+        when(mockConnection.isReadOnly()).thenReturn(true);
+        String xid = "test-commit-readonly";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-commit-readonly"), eq(null), eq(null)))
+                .thenReturn(123L);
+        connectionProxyXA.setAutoCommit(false);
+
+        // Should not throw exception and should be ignored
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.commit(), "Commit on read-only 
transaction should be ignored");
+    }
+
+    @Test
+    public void testRollbackOnAutoCommitSession() throws SQLException, 
XAException {
+        // Test rollback on autocommit session (should be ignored)
+        String xid = "test-rollback-autocommit";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Should not throw exception and should be ignored
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.rollback(), "Rollback on autocommit 
session should be ignored");
+
+        // Verify no XA operations
+        Mockito.verify(mockXAResource, times(0)).end(any(Xid.class), anyInt());
+        Mockito.verify(mockXAResource, times(0)).rollback(any(Xid.class));
+    }
+
+    @Test
+    public void testHoldableMethods() throws SQLException {
+        // Test Holdable interface methods
+        String xid = "test-holdable";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        // Initially not held
+        Assertions.assertFalse(connectionProxyXA.isHeld(), "Connection should 
not be held initially");
+
+        // Set held
+        connectionProxyXA.setHeld(true);
+        Assertions.assertTrue(connectionProxyXA.isHeld(), "Connection should 
be held after setHeld(true)");
+
+        // Set not held
+        connectionProxyXA.setHeld(false);
+        Assertions.assertFalse(connectionProxyXA.isHeld(), "Connection should 
not be held after setHeld(false)");
+    }
+
+    @Test
+    public void testShouldBeHeld() throws SQLException {
+        // Test shouldBeHeld method with different scenarios
+        String xid = "test-should-be-held";
+
+        // When resource says it should be held
+        when(mockDataSourceResource.isShouldBeHeld()).thenReturn(true);
+        ConnectionProxyXA connectionProxyXA1 =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        Assertions.assertTrue(connectionProxyXA1.shouldBeHeld(), "Should be 
held when resource indicates so");
+
+        // When resource says it should not be held, but DB type is blank
+        when(mockDataSourceResource.isShouldBeHeld()).thenReturn(false);
+        when(mockDataSourceResource.getDbType()).thenReturn("");
+        ConnectionProxyXA connectionProxyXA2 =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        Assertions.assertTrue(connectionProxyXA2.shouldBeHeld(), "Should be 
held when DB type is blank");
+
+        // When resource says it should not be held and DB type is not blank
+        when(mockDataSourceResource.getDbType()).thenReturn("mysql");
+        ConnectionProxyXA connectionProxyXA3 =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        Assertions.assertFalse(
+                connectionProxyXA3.shouldBeHeld(),
+                "Should not be held when resource indicates so and DB type is 
not blank");
+    }
+
+    @Test
+    public void testGetResourceLock() throws SQLException {
+        // Test getResourceLock method returns a valid lock
+        String xid = "test-resource-lock";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        ResourceLock resourceLock = connectionProxyXA.getResourceLock();
+        Assertions.assertNotNull(resourceLock, "Resource lock should not be 
null");
+    }
+
+    @Test
+    public void testGetAndSetPrepareTime() throws SQLException {
+        // Test getPrepareTime method (initially null, then set during close)
+        String xid = "test-prepare-time";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        Assertions.assertNull(connectionProxyXA.getPrepareTime(), "Prepare 
time should be null initially");
+    }
+
+    @Test
+    public void testSetCombine() throws SQLException {
+        // Test setCombine method
+        String xid = "test-combine";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Set combine mode
+        connectionProxyXA.setCombine(true);
+
+        // Test that commit returns early in combine mode
+        Assertions.assertDoesNotThrow(() -> connectionProxyXA.commit(), 
"Commit should return early in combine mode");
+
+        // Test that rollback returns early in combine mode
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.rollback(), "Rollback should return 
early in combine mode");
+
+        // Test that close returns early in combine mode
+        Assertions.assertDoesNotThrow(() -> connectionProxyXA.close(), "Close 
should return early in combine mode");
+    }
+
+    @Test
+    public void testCreatePreparedStatement() throws SQLException {
+        // Test createPreparedStatement returns PreparedStatementProxyXA
+        String xid = "test-prepared-statement";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+
+        PreparedStatement mockPreparedStatement = 
Mockito.mock(PreparedStatement.class);
+        when(mockConnection.prepareStatement("SELECT * FROM 
test")).thenReturn(mockPreparedStatement);
+
+        PreparedStatement statement = 
connectionProxyXA.prepareStatement("SELECT * FROM test");
+        Assertions.assertTrue(
+                statement instanceof PreparedStatementProxyXA, "Should return 
PreparedStatementProxyXA instance");
+    }
+
+    @Test
+    public void testXACommitWithResourceLock() throws Exception {
+        // Test xaCommit method with resource lock
+        String xid = "test-xa-commit-lock";
+        long branchId = 12345L;
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Should not throw exception
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.xaCommit(xid, branchId, null), 
"xaCommit should not throw exception");
+
+        // Verify XA commit was called
+        Mockito.verify(mockXAResource).commit(any(Xid.class), eq(false));
+    }
+
+    @Test
+    public void testXARollbackWithResourceLock() throws Exception {
+        // Test xaRollback method with resource lock
+        String xid = "test-xa-rollback-lock";
+        long branchId = 12345L;
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        // Should not throw exception
+        Assertions.assertDoesNotThrow(
+                () -> connectionProxyXA.xaRollback(xid, branchId, null), 
"xaRollback should not throw exception");
+
+        // Verify XA end and rollback were called
+        Mockito.verify(mockXAResource).end(any(Xid.class), 
eq(XAResource.TMFAIL));
+        Mockito.verify(mockXAResource).rollback(any(Xid.class));
+    }
+
+    @Test
+    public void testCloseWithXAReadOnly() throws Exception {
+        // Test close when XA prepare returns XA_RDONLY
+        String xid = "test-close-readonly";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-close-readonly"), eq(null), eq(null)))
+                .thenReturn(123L);
+        
when(mockXAResource.prepare(any(Xid.class))).thenReturn(XAResource.XA_RDONLY);
+
+        connectionProxyXA.setAutoCommit(false);
+
+        // Should not throw exception and should report RDONLY status
+        Assertions.assertDoesNotThrow(() -> connectionProxyXA.close(), "Close 
should handle XA_RDONLY properly");
+
+        // Verify prepare was called
+        Mockito.verify(mockXAResource).prepare(any(Xid.class));
+        // Verify branch report was called with RDONLY status
+        Mockito.verify(mockResourceManager)
+                .branchReport(eq(BranchType.XA), eq(xid), anyLong(), 
eq(BranchStatus.PhaseOne_RDONLY), any());
+    }
+
+    @Test
+    public void testCloseWithXAException() throws Exception {
+        // Test close when XA operations throw exception
+        String xid = "test-close-xa-exception";
+        ConnectionProxyXA connectionProxyXA =
+                new ConnectionProxyXA(mockConnection, mockXAConnection, 
mockDataSourceResource, xid);
+        connectionProxyXA.init();
+
+        when(mockResourceManager.branchRegister(
+                        eq(BranchType.XA), anyString(), eq(null), 
eq("test-close-xa-exception"), eq(null), eq(null)))
+                .thenReturn(123L);
+        when(mockXAResource.prepare(any(Xid.class))).thenThrow(new 
XAException("Prepare failed"));
+
+        connectionProxyXA.setAutoCommit(false);
+
+        SQLException exception = Assertions.assertThrows(
+                SQLException.class,
+                () -> connectionProxyXA.close(),
+                "Close should throw SQLException when XA operations fail");
+
+        Assertions.assertTrue(
+                exception.getMessage().contains("Failed to 
end(TMSUCCESS)/prepare xa branch"),
+                "Exception message should indicate XA failure");
+
+        // Verify branch report was called with Failed status
+        Mockito.verify(mockResourceManager)
+                .branchReport(eq(BranchType.XA), eq(xid), anyLong(), 
eq(BranchStatus.PhaseOne_Failed), any());
+    }
+
     @AfterAll
     public static void tearDown() {
         RootContext.unbind();
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ExecuteTemplateXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ExecuteTemplateXATest.java
new file mode 100644
index 0000000000..89f41293f9
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ExecuteTemplateXATest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.datasource.xa;
+
+import org.apache.seata.rm.datasource.exec.StatementCallback;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * Tests for ExecuteTemplateXA
+ *
+ */
+public class ExecuteTemplateXATest {
+
+    private AbstractConnectionProxyXA mockConnectionProxyXA;
+    private Statement mockStatement;
+    private StatementCallback<String, Statement> stringCallback;
+
+    @BeforeEach
+    public void setUp() throws SQLException {
+        // Mock connection proxy with default autoCommit=true
+        mockConnectionProxyXA = Mockito.mock(AbstractConnectionProxyXA.class);
+        Mockito.when(mockConnectionProxyXA.getAutoCommit()).thenReturn(true);
+
+        // Mock statements
+        mockStatement = Mockito.mock(Statement.class);
+
+        // Default callback that returns "success"
+        stringCallback = (statement, args) -> "success";
+    }
+
+    @Test
+    public void testExecuteSuccessWithAutoCommitTrue() throws SQLException {
+        // Using default setup: autoCommit=true, stringCallback returns 
"success"
+
+        // Execute
+        String result = ExecuteTemplateXA.execute(mockConnectionProxyXA, 
stringCallback, mockStatement);
+
+        // Verify
+        Assertions.assertEquals("success", result);
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).commit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+        Mockito.verify(mockStatement, Mockito.never()).close();
+    }
+
+    @Test
+    public void testExecuteSuccessWithAutoCommitFalse() throws SQLException {
+        // Override default autoCommit to false
+        Mockito.when(mockConnectionProxyXA.getAutoCommit()).thenReturn(false);
+
+        // Execute
+        String result = ExecuteTemplateXA.execute(mockConnectionProxyXA, 
stringCallback, mockStatement);
+
+        // Verify
+        Assertions.assertEquals("success", result);
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA, 
Mockito.never()).setAutoCommit(Mockito.anyBoolean());
+        Mockito.verify(mockConnectionProxyXA, Mockito.never()).commit();
+        Mockito.verify(mockStatement, Mockito.never()).close();
+    }
+
+    @Test
+    public void testExecuteWithSQLExceptionDuringExecution() throws 
SQLException {
+        // Using default setup: autoCommit=true
+
+        // Callback that throws SQLException
+        StatementCallback<String, Statement> failingCallback = (statement, 
args) -> {
+            throw new SQLException("execution failed");
+        };
+
+        // Execute and expect exception
+        SQLException exception = Assertions.assertThrows(SQLException.class, 
() -> {
+            ExecuteTemplateXA.execute(mockConnectionProxyXA, failingCallback, 
mockStatement);
+        });
+
+        // Verify
+        Assertions.assertEquals("execution failed", exception.getMessage());
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).rollback();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+    }
+
+    @Test
+    public void testExecuteWithRuntimeExceptionDuringExecution() throws 
SQLException {
+        StatementCallback<String, Statement> callback = (statement, args) -> {
+            throw new RuntimeException("runtime exception");
+        };
+
+        // Execute and expect exception
+        SQLException exception = Assertions.assertThrows(SQLException.class, 
() -> {
+            ExecuteTemplateXA.execute(mockConnectionProxyXA, callback, 
mockStatement);
+        });
+
+        // Verify
+        Assertions.assertEquals("java.lang.RuntimeException: runtime 
exception", exception.getMessage());
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).rollback();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+    }
+
+    @Test
+    public void testExecuteWithCommitFailure() throws SQLException {
+        Mockito.doThrow(new SQLException("commit failed"))
+                .when(mockConnectionProxyXA)
+                .commit();
+
+        // Execute and expect exception
+        SQLException exception = Assertions.assertThrows(SQLException.class, 
() -> {
+            ExecuteTemplateXA.execute(mockConnectionProxyXA, stringCallback, 
mockStatement);
+        });
+
+        // Verify
+        Assertions.assertEquals("commit failed", exception.getMessage());
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).commit();
+        Mockito.verify(mockConnectionProxyXA).rollback();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+    }
+
+    @Test
+    public void testExecuteWithCommitFailureAndXA_NOT_END() throws 
SQLException {
+
+        // Create SQLException with XA_NOT_END SQLState
+        SQLException xaNotEndException = new SQLException("XA not end", 
AbstractConnectionProxyXA.SQLSTATE_XA_NOT_END);
+        
Mockito.doThrow(xaNotEndException).when(mockConnectionProxyXA).commit();
+
+        // Execute and expect exception
+        SQLException exception = Assertions.assertThrows(SQLException.class, 
() -> {
+            ExecuteTemplateXA.execute(mockConnectionProxyXA, stringCallback, 
mockStatement);
+        });
+
+        // Verify
+        Assertions.assertEquals("XA not end", exception.getMessage());
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).commit();
+        // Should not rollback when XA_NOT_END
+        Mockito.verify(mockConnectionProxyXA, Mockito.never()).rollback();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+    }
+
+    @Test
+    public void testExecuteWithRollbackFailure() throws SQLException {
+
+        Mockito.doThrow(new SQLException("rollback failed"))
+                .when(mockConnectionProxyXA)
+                .rollback();
+
+        StatementCallback<String, Statement> callback = (statement, args) -> {
+            throw new SQLException("execution failed");
+        };
+
+        // Execute and expect the original exception (not the rollback failure)
+        SQLException exception = Assertions.assertThrows(SQLException.class, 
() -> {
+            ExecuteTemplateXA.execute(mockConnectionProxyXA, callback, 
mockStatement);
+        });
+
+        // Verify
+        Assertions.assertEquals("execution failed", exception.getMessage());
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(false);
+        Mockito.verify(mockConnectionProxyXA).rollback();
+        Mockito.verify(mockConnectionProxyXA).setAutoCommit(true);
+    }
+
+    @Test
+    public void testExecuteWithArguments() throws SQLException {
+        Mockito.when(mockConnectionProxyXA.getAutoCommit()).thenReturn(false);
+
+        // Mock statement and callback with arguments
+        PreparedStatement mockStatement = 
Mockito.mock(PreparedStatement.class);
+        StatementCallback<Integer, PreparedStatement> callback = (statement, 
args) -> {
+            Assertions.assertEquals(2, args.length);
+            Assertions.assertEquals("arg1", args[0]);
+            Assertions.assertEquals(42, args[1]);
+            return 1;
+        };
+
+        // Execute with arguments
+        Integer result = ExecuteTemplateXA.execute(mockConnectionProxyXA, 
callback, mockStatement, "arg1", 42);
+
+        // Verify
+        Assertions.assertEquals(1, result);
+        Mockito.verify(mockConnectionProxyXA).getAutoCommit();
+        Mockito.verify(mockConnectionProxyXA, 
Mockito.never()).setAutoCommit(Mockito.anyBoolean());
+    }
+}
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/PreparedStatementProxyXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/PreparedStatementProxyXATest.java
new file mode 100644
index 0000000000..bc25ddd1c5
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/PreparedStatementProxyXATest.java
@@ -0,0 +1,648 @@
+/*
+ * 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.datasource.xa;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+
+/**
+ * Tests for PreparedStatementProxyXA
+ * Focus on verifying actual results and business logic, not just method calls
+ */
+public class PreparedStatementProxyXATest {
+
+    private AbstractConnectionProxyXA mockConnectionProxyXA;
+    private PreparedStatement mockPreparedStatement;
+    private PreparedStatementProxyXA preparedStatementProxyXA;
+
+    @BeforeEach
+    public void setUp() {
+        mockConnectionProxyXA = Mockito.mock(AbstractConnectionProxyXA.class);
+        mockPreparedStatement = Mockito.mock(PreparedStatement.class);
+        preparedStatementProxyXA = new 
PreparedStatementProxyXA(mockConnectionProxyXA, mockPreparedStatement);
+    }
+
+    @Test
+    public void testExecuteQueryReturnsCorrectResultSet() throws SQLException {
+        // Verify executeQuery returns the correct ResultSet through XA 
transaction flow
+        ResultSet expectedResultSet = Mockito.mock(ResultSet.class);
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedResultSet);
+
+            ResultSet actualResultSet = 
preparedStatementProxyXA.executeQuery();
+
+            Assertions.assertSame(
+                    expectedResultSet,
+                    actualResultSet,
+                    "executeQuery should return the exact ResultSet from 
ExecuteTemplateXA");
+        }
+    }
+
+    @Test
+    public void testExecuteUpdateReturnsCorrectCount() throws SQLException {
+        // Verify executeUpdate returns the correct update count through XA 
transaction flow
+        int expectedUpdateCount = 42;
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedUpdateCount);
+
+            int actualUpdateCount = preparedStatementProxyXA.executeUpdate();
+
+            Assertions.assertEquals(
+                    expectedUpdateCount,
+                    actualUpdateCount,
+                    "executeUpdate should return the exact count from 
ExecuteTemplateXA");
+        }
+    }
+
+    @Test
+    public void testExecuteReturnsCorrectBoolean() throws SQLException {
+        // Verify execute returns the correct boolean result through XA 
transaction flow
+        boolean expectedResult = true;
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedResult);
+
+            boolean actualResult = preparedStatementProxyXA.execute();
+
+            Assertions.assertEquals(
+                    expectedResult, actualResult, "execute should return the 
exact boolean from ExecuteTemplateXA");
+        }
+    }
+
+    @Test
+    public void testExecuteQueryPropagatesException() {
+        // Verify exceptions are correctly propagated from XA transaction 
context
+        SQLException expectedException = new SQLException("Query execution 
failed");
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenThrow(expectedException);
+
+            SQLException actualException = 
Assertions.assertThrows(SQLException.class, () -> {
+                preparedStatementProxyXA.executeQuery();
+            });
+
+            Assertions.assertSame(
+                    expectedException, actualException, "Exception should be 
propagated without modification");
+        }
+    }
+
+    @Test
+    public void testGetMetaDataReturnsCorrectMetadata() throws SQLException {
+        // Verify getMetaData returns the correct metadata object
+        ResultSetMetaData expectedMetaData = 
Mockito.mock(ResultSetMetaData.class);
+
+        
Mockito.when(mockPreparedStatement.getMetaData()).thenReturn(expectedMetaData);
+
+        ResultSetMetaData actualMetaData = 
preparedStatementProxyXA.getMetaData();
+
+        Assertions.assertSame(
+                expectedMetaData,
+                actualMetaData,
+                "getMetaData should return the exact metadata from underlying 
statement");
+    }
+
+    @Test
+    public void testGetParameterMetaDataReturnsCorrectMetadata() throws 
SQLException {
+        // Verify getParameterMetaData returns the correct parameter metadata 
object
+        ParameterMetaData expectedParamMetaData = 
Mockito.mock(ParameterMetaData.class);
+
+        
Mockito.when(mockPreparedStatement.getParameterMetaData()).thenReturn(expectedParamMetaData);
+
+        ParameterMetaData actualParamMetaData = 
preparedStatementProxyXA.getParameterMetaData();
+
+        Assertions.assertSame(
+                expectedParamMetaData,
+                actualParamMetaData,
+                "getParameterMetaData should return the exact parameter 
metadata from underlying statement");
+    }
+
+    @Test
+    public void testParameterSettingDoesNotBreakExecution() throws 
SQLException {
+        // Verify that setting various parameters doesn't break query execution
+        BigDecimal testDecimal = new BigDecimal("123.45");
+        Date testDate = new Date(System.currentTimeMillis());
+        ResultSet expectedResultSet = Mockito.mock(ResultSet.class);
+
+        // Set various parameters
+        preparedStatementProxyXA.setString(1, "testString");
+        preparedStatementProxyXA.setInt(2, 42);
+        preparedStatementProxyXA.setLong(3, 123456789L);
+        preparedStatementProxyXA.setBigDecimal(4, testDecimal);
+        preparedStatementProxyXA.setDate(5, testDate);
+        preparedStatementProxyXA.setNull(6, Types.VARCHAR);
+
+        // Execute query and verify it returns the expected result
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedResultSet);
+
+            ResultSet actualResultSet = 
preparedStatementProxyXA.executeQuery();
+
+            Assertions.assertSame(
+                    expectedResultSet,
+                    actualResultSet,
+                    "Query should execute successfully and return expected 
ResultSet after setting parameters");
+        }
+    }
+
+    @Test
+    public void testStreamParametersDoNotBreakExecution() throws SQLException {
+        // Verify that setting stream parameters doesn't break query execution
+        InputStream mockInputStream = Mockito.mock(InputStream.class);
+        Reader mockReader = Mockito.mock(Reader.class);
+        Blob mockBlob = Mockito.mock(Blob.class);
+        int expectedUpdateCount = 7;
+
+        // Set stream parameters
+        preparedStatementProxyXA.setAsciiStream(1, mockInputStream, 100);
+        preparedStatementProxyXA.setBinaryStream(2, mockInputStream, 200);
+        preparedStatementProxyXA.setCharacterStream(3, mockReader, 300);
+        preparedStatementProxyXA.setBlob(4, mockBlob);
+
+        // Execute update and verify it returns the expected count
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedUpdateCount);
+
+            int actualUpdateCount = preparedStatementProxyXA.executeUpdate();
+
+            Assertions.assertEquals(
+                    expectedUpdateCount,
+                    actualUpdateCount,
+                    "Update should execute successfully and return expected 
count after setting stream parameters");
+        }
+    }
+
+    @Test
+    public void testComplexParametersDoNotBreakExecution() throws SQLException 
{
+        // Verify that setting complex parameters (dates with calendar, 
objects) doesn't break execution
+        Date testDate = new Date(System.currentTimeMillis());
+        Time testTime = new Time(System.currentTimeMillis());
+        Timestamp testTimestamp = new Timestamp(System.currentTimeMillis());
+        Calendar testCalendar = Calendar.getInstance();
+        BigDecimal testDecimal = new BigDecimal("999.99");
+        boolean expectedResult = true;
+
+        // Set complex parameters
+        preparedStatementProxyXA.setDate(1, testDate, testCalendar);
+        preparedStatementProxyXA.setTime(2, testTime, testCalendar);
+        preparedStatementProxyXA.setTimestamp(3, testTimestamp, testCalendar);
+        preparedStatementProxyXA.setObject(4, "testObject");
+        preparedStatementProxyXA.setObject(5, testDecimal, Types.DECIMAL);
+        preparedStatementProxyXA.setObject(6, testDecimal, Types.DECIMAL, 2);
+
+        // Execute and verify it returns the expected result
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedResult);
+
+            boolean actualResult = preparedStatementProxyXA.execute();
+
+            Assertions.assertEquals(
+                    expectedResult,
+                    actualResult,
+                    "Execute should return expected result after setting 
complex parameters");
+        }
+    }
+
+    @Test
+    public void testInheritedGetterMethodsReturnCorrectValues() throws 
SQLException {
+        // Verify that methods inherited from StatementProxyXA return correct 
values
+        Connection expectedConnection = Mockito.mock(Connection.class);
+        ResultSet expectedResultSet = Mockito.mock(ResultSet.class);
+        SQLWarning expectedWarning = Mockito.mock(SQLWarning.class);
+
+        
Mockito.when(mockPreparedStatement.getConnection()).thenReturn(expectedConnection);
+        
Mockito.when(mockPreparedStatement.getResultSet()).thenReturn(expectedResultSet);
+        Mockito.when(mockPreparedStatement.getUpdateCount()).thenReturn(100);
+        
Mockito.when(mockPreparedStatement.getWarnings()).thenReturn(expectedWarning);
+        Mockito.when(mockPreparedStatement.getMaxRows()).thenReturn(1000);
+        Mockito.when(mockPreparedStatement.getQueryTimeout()).thenReturn(30);
+        Mockito.when(mockPreparedStatement.isClosed()).thenReturn(false);
+        Mockito.when(mockPreparedStatement.getFetchSize()).thenReturn(50);
+        
Mockito.when(mockPreparedStatement.getResultSetConcurrency()).thenReturn(ResultSet.CONCUR_READ_ONLY);
+        
Mockito.when(mockPreparedStatement.getResultSetType()).thenReturn(ResultSet.TYPE_FORWARD_ONLY);
+
+        // Verify all getter methods return correct values
+        Assertions.assertSame(
+                expectedConnection,
+                preparedStatementProxyXA.getConnection(),
+                "getConnection should return the correct connection");
+        Assertions.assertSame(
+                expectedResultSet,
+                preparedStatementProxyXA.getResultSet(),
+                "getResultSet should return the correct result set");
+        Assertions.assertEquals(
+                100, preparedStatementProxyXA.getUpdateCount(), 
"getUpdateCount should return the correct count");
+        Assertions.assertSame(
+                expectedWarning,
+                preparedStatementProxyXA.getWarnings(),
+                "getWarnings should return the correct warning");
+        Assertions.assertEquals(
+                1000, preparedStatementProxyXA.getMaxRows(), "getMaxRows 
should return the correct value");
+        Assertions.assertEquals(
+                30, preparedStatementProxyXA.getQueryTimeout(), 
"getQueryTimeout should return the correct timeout");
+        Assertions.assertFalse(preparedStatementProxyXA.isClosed(), "isClosed 
should return the correct state");
+        Assertions.assertEquals(
+                50, preparedStatementProxyXA.getFetchSize(), "getFetchSize 
should return the correct size");
+        Assertions.assertEquals(
+                ResultSet.CONCUR_READ_ONLY,
+                preparedStatementProxyXA.getResultSetConcurrency(),
+                "getResultSetConcurrency should return the correct 
concurrency");
+        Assertions.assertEquals(
+                ResultSet.TYPE_FORWARD_ONLY,
+                preparedStatementProxyXA.getResultSetType(),
+                "getResultSetType should return the correct type");
+    }
+
+    @Test
+    public void testConstructorAndGetTargetStatement() {
+        // Verify constructor properly initializes and getTargetStatement 
returns correct object
+        AbstractConnectionProxyXA testConnectionProxy = 
Mockito.mock(AbstractConnectionProxyXA.class);
+        PreparedStatement testPreparedStatement = 
Mockito.mock(PreparedStatement.class);
+
+        PreparedStatementProxyXA proxy = new 
PreparedStatementProxyXA(testConnectionProxy, testPreparedStatement);
+
+        // The getTargetStatement method is private, but we can verify it 
works through other methods
+        Assertions.assertNotNull(proxy, "Constructor should create a valid 
proxy instance");
+
+        // Verify that the proxy uses the correct target statement by checking 
method delegation
+        try {
+            proxy.clearParameters();
+            Mockito.verify(testPreparedStatement).clearParameters();
+        } catch (SQLException e) {
+            // This is fine for the test, we just want to verify delegation
+        }
+    }
+
+    @Test
+    public void testBasicParameterSetters() throws SQLException {
+        // Test all basic parameter setter methods to improve coverage
+        preparedStatementProxyXA.setBoolean(1, true);
+        preparedStatementProxyXA.setByte(2, (byte) 127);
+        preparedStatementProxyXA.setShort(3, (short) 32767);
+        preparedStatementProxyXA.setFloat(4, 3.14f);
+        preparedStatementProxyXA.setDouble(5, 2.718281828);
+        preparedStatementProxyXA.setBytes(6, new byte[] {1, 2, 3, 4, 5});
+
+        // Verify all calls were delegated to the underlying statement
+        Mockito.verify(mockPreparedStatement).setBoolean(1, true);
+        Mockito.verify(mockPreparedStatement).setByte(2, (byte) 127);
+        Mockito.verify(mockPreparedStatement).setShort(3, (short) 32767);
+        Mockito.verify(mockPreparedStatement).setFloat(4, 3.14f);
+        Mockito.verify(mockPreparedStatement).setDouble(5, 2.718281828);
+        Mockito.verify(mockPreparedStatement).setBytes(6, new byte[] {1, 2, 3, 
4, 5});
+    }
+
+    @Test
+    public void testTimeRelatedParameterSetters() throws SQLException {
+        // Test time-related parameter setters
+        Time testTime = new Time(System.currentTimeMillis());
+        Timestamp testTimestamp = new Timestamp(System.currentTimeMillis());
+
+        preparedStatementProxyXA.setTime(1, testTime);
+        preparedStatementProxyXA.setTimestamp(2, testTimestamp);
+
+        // Verify calls were delegated
+        Mockito.verify(mockPreparedStatement).setTime(1, testTime);
+        Mockito.verify(mockPreparedStatement).setTimestamp(2, testTimestamp);
+    }
+
+    @Test
+    public void testLargeObjectAndSpecialParameterSetters() throws 
SQLException {
+        // Test setters for large objects and special parameters
+        Ref mockRef = Mockito.mock(Ref.class);
+        Clob mockClob = Mockito.mock(Clob.class);
+        Array mockArray = Mockito.mock(Array.class);
+        URL testURL = Mockito.mock(URL.class);
+        RowId mockRowId = Mockito.mock(RowId.class);
+
+        preparedStatementProxyXA.setRef(1, mockRef);
+        preparedStatementProxyXA.setClob(2, mockClob);
+        preparedStatementProxyXA.setArray(3, mockArray);
+        preparedStatementProxyXA.setURL(4, testURL);
+        preparedStatementProxyXA.setRowId(5, mockRowId);
+        preparedStatementProxyXA.setNull(6, Types.VARCHAR, "VARCHAR");
+
+        // Verify all calls were delegated
+        Mockito.verify(mockPreparedStatement).setRef(1, mockRef);
+        Mockito.verify(mockPreparedStatement).setClob(2, mockClob);
+        Mockito.verify(mockPreparedStatement).setArray(3, mockArray);
+        Mockito.verify(mockPreparedStatement).setURL(4, testURL);
+        Mockito.verify(mockPreparedStatement).setRowId(5, mockRowId);
+        Mockito.verify(mockPreparedStatement).setNull(6, Types.VARCHAR, 
"VARCHAR");
+    }
+
+    @Test
+    public void testNationalCharacterSetters() throws SQLException {
+        // Test national character set related setters
+        Reader mockReader = Mockito.mock(Reader.class);
+        NClob mockNClob = Mockito.mock(NClob.class);
+
+        preparedStatementProxyXA.setNString(1, "国际化字符串");
+        preparedStatementProxyXA.setNCharacterStream(2, mockReader, 100L);
+        preparedStatementProxyXA.setNClob(3, mockNClob);
+        preparedStatementProxyXA.setNCharacterStream(4, mockReader);
+        preparedStatementProxyXA.setNClob(5, mockReader, 200L);
+        preparedStatementProxyXA.setNClob(6, mockReader);
+
+        // Verify all calls were delegated
+        Mockito.verify(mockPreparedStatement).setNString(1, "国际化字符串");
+        Mockito.verify(mockPreparedStatement).setNCharacterStream(2, 
mockReader, 100L);
+        Mockito.verify(mockPreparedStatement).setNClob(3, mockNClob);
+        Mockito.verify(mockPreparedStatement).setNCharacterStream(4, 
mockReader);
+        Mockito.verify(mockPreparedStatement).setNClob(5, mockReader, 200L);
+        Mockito.verify(mockPreparedStatement).setNClob(6, mockReader);
+    }
+
+    @Test
+    public void testStreamSettersWithDifferentLengthParams() throws 
SQLException {
+        // Test stream setters with different length parameter variants
+        InputStream mockInputStream = Mockito.mock(InputStream.class);
+        Reader mockReader = Mockito.mock(Reader.class);
+
+        // Test long length variants
+        preparedStatementProxyXA.setAsciiStream(1, mockInputStream, 1000L);
+        preparedStatementProxyXA.setBinaryStream(2, mockInputStream, 2000L);
+        preparedStatementProxyXA.setCharacterStream(3, mockReader, 3000L);
+
+        // Test no-length variants
+        preparedStatementProxyXA.setAsciiStream(4, mockInputStream);
+        preparedStatementProxyXA.setBinaryStream(5, mockInputStream);
+        preparedStatementProxyXA.setCharacterStream(6, mockReader);
+
+        // Test Unicode stream (deprecated but still needs coverage)
+        preparedStatementProxyXA.setUnicodeStream(7, mockInputStream, 500);
+
+        // Verify all calls were delegated
+        Mockito.verify(mockPreparedStatement).setAsciiStream(1, 
mockInputStream, 1000L);
+        Mockito.verify(mockPreparedStatement).setBinaryStream(2, 
mockInputStream, 2000L);
+        Mockito.verify(mockPreparedStatement).setCharacterStream(3, 
mockReader, 3000L);
+        Mockito.verify(mockPreparedStatement).setAsciiStream(4, 
mockInputStream);
+        Mockito.verify(mockPreparedStatement).setBinaryStream(5, 
mockInputStream);
+        Mockito.verify(mockPreparedStatement).setCharacterStream(6, 
mockReader);
+        Mockito.verify(mockPreparedStatement).setUnicodeStream(7, 
mockInputStream, 500);
+    }
+
+    @Test
+    public void testBlobAndClobVariantSetters() throws SQLException {
+        // Test various Blob and Clob setter variants
+        InputStream mockInputStream = Mockito.mock(InputStream.class);
+        Reader mockReader = Mockito.mock(Reader.class);
+
+        // Test Blob variants
+        preparedStatementProxyXA.setBlob(1, mockInputStream, 1000L);
+        preparedStatementProxyXA.setBlob(2, mockInputStream);
+
+        // Test Clob variants
+        preparedStatementProxyXA.setClob(3, mockReader, 2000L);
+        preparedStatementProxyXA.setClob(4, mockReader);
+
+        // Verify all calls were delegated
+        Mockito.verify(mockPreparedStatement).setBlob(1, mockInputStream, 
1000L);
+        Mockito.verify(mockPreparedStatement).setBlob(2, mockInputStream);
+        Mockito.verify(mockPreparedStatement).setClob(3, mockReader, 2000L);
+        Mockito.verify(mockPreparedStatement).setClob(4, mockReader);
+    }
+
+    @Test
+    public void testSQLXMLSetter() throws SQLException {
+        // Test SQLXML parameter setter
+        SQLXML mockSQLXML = Mockito.mock(SQLXML.class);
+
+        preparedStatementProxyXA.setSQLXML(1, mockSQLXML);
+
+        // Verify call was delegated
+        Mockito.verify(mockPreparedStatement).setSQLXML(1, mockSQLXML);
+    }
+
+    @Test
+    public void testBatchAndParameterManagement() throws SQLException {
+        // Test batch and parameter management methods
+        preparedStatementProxyXA.addBatch();
+        preparedStatementProxyXA.clearParameters();
+
+        // Verify calls were delegated
+        Mockito.verify(mockPreparedStatement).addBatch();
+        Mockito.verify(mockPreparedStatement).clearParameters();
+    }
+
+    @Test
+    public void testParameterSettersWithNullValues() throws SQLException {
+        // Test parameter setters with null values where applicable
+        preparedStatementProxyXA.setString(1, null);
+        preparedStatementProxyXA.setBigDecimal(2, null);
+        preparedStatementProxyXA.setDate(3, null);
+        preparedStatementProxyXA.setTime(4, null);
+        preparedStatementProxyXA.setTimestamp(5, null);
+        preparedStatementProxyXA.setBytes(6, null);
+        preparedStatementProxyXA.setRef(7, null);
+        preparedStatementProxyXA.setBlob(8, (Blob) null);
+        preparedStatementProxyXA.setClob(9, (Clob) null);
+        preparedStatementProxyXA.setArray(10, null);
+        preparedStatementProxyXA.setObject(11, null);
+
+        // Verify all null values were handled correctly
+        Mockito.verify(mockPreparedStatement).setString(1, null);
+        Mockito.verify(mockPreparedStatement).setBigDecimal(2, null);
+        Mockito.verify(mockPreparedStatement).setDate(3, null);
+        Mockito.verify(mockPreparedStatement).setTime(4, null);
+        Mockito.verify(mockPreparedStatement).setTimestamp(5, null);
+        Mockito.verify(mockPreparedStatement).setBytes(6, null);
+        Mockito.verify(mockPreparedStatement).setRef(7, null);
+        Mockito.verify(mockPreparedStatement).setBlob(8, (Blob) null);
+        Mockito.verify(mockPreparedStatement).setClob(9, (Clob) null);
+        Mockito.verify(mockPreparedStatement).setArray(10, null);
+        Mockito.verify(mockPreparedStatement).setObject(11, null);
+    }
+
+    @Test
+    public void testParameterSettersThrowSQLException() throws SQLException {
+        // Test that SQL exceptions from parameter setters are properly 
propagated
+        SQLException expectedException = new SQLException("Parameter setting 
failed");
+
+        
Mockito.doThrow(expectedException).when(mockPreparedStatement).setString(1, 
"test");
+
+        SQLException actualException = 
Assertions.assertThrows(SQLException.class, () -> {
+            preparedStatementProxyXA.setString(1, "test");
+        });
+
+        Assertions.assertSame(
+                expectedException,
+                actualException,
+                "SQLException from parameter setter should be propagated 
without modification");
+    }
+
+    @Test
+    public void testMetaDataMethodsThrowSQLException() throws SQLException {
+        // Test that SQL exceptions from metadata methods are properly 
propagated
+        SQLException expectedException = new SQLException("Metadata access 
failed");
+
+        
Mockito.when(mockPreparedStatement.getMetaData()).thenThrow(expectedException);
+
+        SQLException actualException = 
Assertions.assertThrows(SQLException.class, () -> {
+            preparedStatementProxyXA.getMetaData();
+        });
+
+        Assertions.assertSame(
+                expectedException,
+                actualException,
+                "SQLException from getMetaData should be propagated without 
modification");
+    }
+
+    @Test
+    public void testExecuteUpdatePropagatesException() {
+        // Test that exceptions from executeUpdate are properly propagated
+        SQLException expectedException = new SQLException("Update execution 
failed");
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenThrow(expectedException);
+
+            SQLException actualException = 
Assertions.assertThrows(SQLException.class, () -> {
+                preparedStatementProxyXA.executeUpdate();
+            });
+
+            Assertions.assertSame(
+                    expectedException,
+                    actualException,
+                    "Exception from executeUpdate should be propagated without 
modification");
+        }
+    }
+
+    @Test
+    public void testExecutePropagatesException() {
+        // Test that exceptions from execute are properly propagated
+        SQLException expectedException = new SQLException("Execute failed");
+
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenThrow(expectedException);
+
+            SQLException actualException = 
Assertions.assertThrows(SQLException.class, () -> {
+                preparedStatementProxyXA.execute();
+            });
+
+            Assertions.assertSame(
+                    expectedException,
+                    actualException,
+                    "Exception from execute should be propagated without 
modification");
+        }
+    }
+
+    @Test
+    public void testComprehensiveParameterSettingWithExecution() throws 
SQLException {
+        // Comprehensive test setting various parameters and then executing 
successfully
+        InputStream mockInputStream = Mockito.mock(InputStream.class);
+        Reader mockReader = Mockito.mock(Reader.class);
+        Blob mockBlob = Mockito.mock(Blob.class);
+        Clob mockClob = Mockito.mock(Clob.class);
+        Array mockArray = Mockito.mock(Array.class);
+        Ref mockRef = Mockito.mock(Ref.class);
+        ResultSet expectedResultSet = Mockito.mock(ResultSet.class);
+
+        // Set a comprehensive set of parameters
+        preparedStatementProxyXA.setBoolean(1, false);
+        preparedStatementProxyXA.setByte(2, (byte) -128);
+        preparedStatementProxyXA.setShort(3, (short) -32768);
+        preparedStatementProxyXA.setInt(4, -2147483648);
+        preparedStatementProxyXA.setLong(5, -9223372036854775808L);
+        preparedStatementProxyXA.setFloat(6, Float.MIN_VALUE);
+        preparedStatementProxyXA.setDouble(7, Double.MIN_VALUE);
+        preparedStatementProxyXA.setBigDecimal(8, new 
BigDecimal("-999999.999999"));
+        preparedStatementProxyXA.setString(9, "测试中文字符串");
+        preparedStatementProxyXA.setBytes(10, new byte[] {-1, 0, 1});
+        preparedStatementProxyXA.setDate(11, new Date(0));
+        preparedStatementProxyXA.setTime(12, new Time(0));
+        preparedStatementProxyXA.setTimestamp(13, new Timestamp(0));
+        preparedStatementProxyXA.setAsciiStream(14, mockInputStream);
+        preparedStatementProxyXA.setBinaryStream(15, mockInputStream);
+        preparedStatementProxyXA.setCharacterStream(16, mockReader);
+        preparedStatementProxyXA.setObject(17, "testObject");
+        preparedStatementProxyXA.setBlob(18, mockBlob);
+        preparedStatementProxyXA.setClob(19, mockClob);
+        preparedStatementProxyXA.setArray(20, mockArray);
+        preparedStatementProxyXA.setRef(21, mockRef);
+        preparedStatementProxyXA.setNull(22, Types.INTEGER);
+
+        // Execute query and verify success
+        try (MockedStatic<ExecuteTemplateXA> mockedExecuteTemplate = 
Mockito.mockStatic(ExecuteTemplateXA.class)) {
+            mockedExecuteTemplate
+                    .when(() -> ExecuteTemplateXA.execute(
+                            Mockito.eq(mockConnectionProxyXA), Mockito.any(), 
Mockito.eq(mockPreparedStatement)))
+                    .thenReturn(expectedResultSet);
+
+            ResultSet actualResultSet = 
preparedStatementProxyXA.executeQuery();
+
+            Assertions.assertSame(
+                    expectedResultSet,
+                    actualResultSet,
+                    "Query should execute successfully after setting 
comprehensive parameters");
+        }
+    }
+}
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ResourceManagerXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ResourceManagerXATest.java
new file mode 100644
index 0000000000..3c1d5cf02c
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ResourceManagerXATest.java
@@ -0,0 +1,354 @@
+/*
+ * 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.datasource.xa;
+
+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.Resource;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import javax.transaction.xa.XAException;
+import java.lang.reflect.Field;
+import java.util.Map;
+
+/**
+ * Tests for ResourceManagerXA
+ *
+ */
+public class ResourceManagerXATest {
+
+    private ResourceManagerXA resourceManagerXA;
+
+    @BeforeEach
+    public void setUp() {
+        resourceManagerXA = new ResourceManagerXA();
+    }
+
+    @Test
+    public void testInit() {
+        // Test init method - should not throw exception
+        Assertions.assertDoesNotThrow(() -> resourceManagerXA.init());
+    }
+
+    @Test
+    public void testGetBranchType() {
+        Assertions.assertEquals(BranchType.XA, 
resourceManagerXA.getBranchType());
+    }
+
+    @Test
+    public void testInitXaTwoPhaseTimeoutChecker() {
+        // Test initialization of timeout checker
+        Assertions.assertDoesNotThrow(() -> 
resourceManagerXA.initXaTwoPhaseTimeoutChecker());
+
+        // Call again to test the already initialized case
+        Assertions.assertDoesNotThrow(() -> 
resourceManagerXA.initXaTwoPhaseTimeoutChecker());
+    }
+
+    @Test
+    public void testBranchCommitSuccess() throws Exception {
+        // Mock data source and connection
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Setup mock behavior
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+        Mockito.doNothing()
+                .when(mockConnectionProxyXA)
+                .xaCommit(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch commit
+        BranchStatus result =
+                resourceManagerXA.branchCommit(BranchType.XA, "testXid", 123L, 
"testResource", "testData");
+
+        Assertions.assertEquals(BranchStatus.PhaseTwo_Committed, result);
+        
Mockito.verify(mockDataSourceProxyXA).getConnectionForXAFinish(Mockito.any(XAXid.class));
+        Mockito.verify(mockConnectionProxyXA).xaCommit("testXid", 123L, 
"testData");
+        Mockito.verify(mockConnectionProxyXA).close();
+    }
+
+    @Test
+    public void testBranchRollbackSuccess() throws Exception {
+        // Mock data source and connection
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Setup mock behavior
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+        Mockito.doNothing()
+                .when(mockConnectionProxyXA)
+                .xaRollback(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch rollback
+        BranchStatus result =
+                resourceManagerXA.branchRollback(BranchType.XA, "testXid", 
123L, "testResource", "testData");
+
+        Assertions.assertEquals(BranchStatus.PhaseTwo_Rollbacked, result);
+        
Mockito.verify(mockDataSourceProxyXA).getConnectionForXAFinish(Mockito.any(XAXid.class));
+        Mockito.verify(mockConnectionProxyXA).xaRollback("testXid", 123L, 
"testData");
+        Mockito.verify(mockConnectionProxyXA).close();
+    }
+
+    @Test
+    public void testBranchCommitWithXAExceptionXAER_NOTA() throws Exception {
+        // Mock data source and connection that throws XAException
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException with XAER_NOTA and setup mock to throw it
+        XAException xaException = new XAException("XAER_NOTA");
+        xaException.errorCode = XAException.XAER_NOTA;
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaCommit(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch commit with XAER_NOTA exception
+        BranchStatus result =
+                resourceManagerXA.branchCommit(BranchType.XA, "testXid", 123L, 
"testResource", "testData");
+
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_CommitFailed_XAER_NOTA_Retryable, 
result);
+        Mockito.verify(mockConnectionProxyXA).xaCommit("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchCommitWithXAException() throws Exception {
+        // Mock data source and connection that throws XAException
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException and setup mock to throw it
+        XAException xaException = new XAException("XA error");
+        xaException.errorCode = XAException.XA_RBROLLBACK;
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaCommit(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch commit with XAException
+        BranchStatus result =
+                resourceManagerXA.branchCommit(BranchType.XA, "testXid", 123L, 
"testResource", "testData");
+
+        Assertions.assertEquals(BranchStatus.PhaseTwo_CommitFailed_Retryable, 
result);
+        Mockito.verify(mockConnectionProxyXA).xaCommit("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchCommitWithXAExceptionAsSQLException() throws 
Exception {
+        // Mock data source and connection that throws XAException (which is a 
subclass of SQLException)
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException (which extends SQLException) and setup mock to 
throw it
+        XAException xaException = new XAException("XA error");
+        xaException.errorCode = XAException.XA_RBROLLBACK; // Not XAER_NOTA, 
so it should be treated as SQLException
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaCommit(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch commit with XAException (treated as SQLException)
+        BranchStatus result =
+                resourceManagerXA.branchCommit(BranchType.XA, "testXid", 123L, 
"testResource", "testData");
+
+        Assertions.assertEquals(BranchStatus.PhaseTwo_CommitFailed_Retryable, 
result);
+        Mockito.verify(mockConnectionProxyXA).xaCommit("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchRollbackWithXAExceptionXAER_NOTA() throws Exception {
+        // Mock data source and connection that throws XAException
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException with XAER_NOTA and setup mock to throw it
+        XAException xaException = new XAException("XAER_NOTA");
+        xaException.errorCode = XAException.XAER_NOTA;
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaRollback(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch rollback with XAER_NOTA exception
+        BranchStatus result =
+                resourceManagerXA.branchRollback(BranchType.XA, "testXid", 
123L, "testResource", "testData");
+
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_RollbackFailed_XAER_NOTA_Retryable,
 result);
+        Mockito.verify(mockConnectionProxyXA).xaRollback("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchRollbackWithXAException() throws Exception {
+        // Mock data source and connection that throws XAException
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException and setup mock to throw it
+        XAException xaException = new XAException("XA error");
+        xaException.errorCode = XAException.XA_RBROLLBACK;
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaRollback(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch rollback with XAException
+        BranchStatus result =
+                resourceManagerXA.branchRollback(BranchType.XA, "testXid", 
123L, "testResource", "testData");
+
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_RollbackFailed_Retryable, result);
+        Mockito.verify(mockConnectionProxyXA).xaRollback("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchRollbackWithXAExceptionAsSQLException() throws 
Exception {
+        // Mock data source and connection that throws XAException (which is a 
subclass of SQLException)
+        AbstractDataSourceProxyXA mockDataSourceProxyXA = 
Mockito.mock(AbstractDataSourceProxyXA.class);
+        ConnectionProxyXA mockConnectionProxyXA = 
Mockito.mock(ConnectionProxyXA.class);
+
+        // Create XAException (which extends SQLException) and setup mock to 
throw it
+        XAException xaException = new XAException("XA error");
+        xaException.errorCode = XAException.XA_RBROLLBACK; // Not XAER_NOTA, 
so it should be treated as SQLException
+        Mockito.doThrow(xaException)
+                .when(mockConnectionProxyXA)
+                .xaRollback(Mockito.anyString(), Mockito.anyLong(), 
Mockito.anyString());
+        Mockito.doNothing().when(mockConnectionProxyXA).close();
+
+        
Mockito.when(mockDataSourceProxyXA.getConnectionForXAFinish(Mockito.any(XAXid.class)))
+                .thenReturn(mockConnectionProxyXA);
+
+        // Use reflection to set the dataSourceCache field
+        Field dataSourceCacheField = 
ResourceManagerXA.class.getSuperclass().getDeclaredField("dataSourceCache");
+        dataSourceCacheField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Resource> dataSourceCache = (Map<String, Resource>) 
dataSourceCacheField.get(resourceManagerXA);
+        dataSourceCache.put("testResource", mockDataSourceProxyXA);
+
+        // Test branch rollback with XAException (treated as SQLException)
+        BranchStatus result =
+                resourceManagerXA.branchRollback(BranchType.XA, "testXid", 
123L, "testResource", "testData");
+
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_RollbackFailed_Retryable, result);
+        Mockito.verify(mockConnectionProxyXA).xaRollback("testXid", 123L, 
"testData");
+    }
+
+    @Test
+    public void testBranchCommitWithUnknownResource() throws 
TransactionException {
+        // Test with unknown resource ID
+        BranchStatus result =
+                resourceManagerXA.branchCommit(BranchType.XA, "testXid", 123L, 
"unknownResource", "testData");
+
+        // Should return failure status for unknown resource
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_CommitFailed_Unretryable, result);
+    }
+
+    @Test
+    public void testBranchRollbackWithUnknownResource() throws 
TransactionException {
+        // Test with unknown resource ID
+        BranchStatus result =
+                resourceManagerXA.branchRollback(BranchType.XA, "testXid", 
123L, "unknownResource", "testData");
+
+        // Should return failure status for unknown resource
+        
Assertions.assertEquals(BranchStatus.PhaseTwo_RollbackFailed_Unretryable, 
result);
+    }
+
+    @Test
+    public void testInitXaTwoPhaseTimeoutCheckerWithNoResources() {
+        // Test with no resources that need holding
+        Assertions.assertDoesNotThrow(() -> 
resourceManagerXA.initXaTwoPhaseTimeoutChecker());
+
+        // Should not create a scheduler when no resources need holding
+        // This is hard to test directly without accessing private fields
+    }
+
+    @Test
+    public void testInitXaTwoPhaseTimeoutCheckerWithResourcesNeedingHold() {
+        // This test would require setting up mock resources that return true 
for isShouldBeHeld()
+        // Due to the complexity of mocking the dataSourceCache, we'll skip 
this for now
+        Assertions.assertDoesNotThrow(() -> 
resourceManagerXA.initXaTwoPhaseTimeoutChecker());
+    }
+}
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/StatementProxyXATest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/StatementProxyXATest.java
new file mode 100644
index 0000000000..77acaeb56d
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/StatementProxyXATest.java
@@ -0,0 +1,567 @@
+/*
+ * 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.datasource.xa;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+
+/**
+ * Tests for StatementProxyXA
+ *
+ */
+public class StatementProxyXATest {
+
+    private AbstractConnectionProxyXA mockConnectionProxyXA;
+    private Statement mockStatement;
+    private StatementProxyXA statementProxyXA;
+
+    @BeforeEach
+    public void setUp() {
+        mockConnectionProxyXA = Mockito.mock(AbstractConnectionProxyXA.class);
+        mockStatement = Mockito.mock(Statement.class);
+        statementProxyXA = new StatementProxyXA(mockConnectionProxyXA, 
mockStatement);
+    }
+
+    @Test
+    public void testExecuteUpdate() throws SQLException {
+        String sql = "UPDATE test SET name = 'test' WHERE id = 1";
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public int executeUpdate(String sql) throws SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeUpdate(sql);
+            }
+        };
+
+        Mockito.when(mockStatement.executeUpdate(sql)).thenReturn(1);
+
+        int result = testProxy.executeUpdate(sql);
+
+        Assertions.assertEquals(1, result);
+        Mockito.verify(mockStatement).executeUpdate(sql);
+    }
+
+    @Test
+    public void testExecuteUpdateWithAutoGeneratedKeys() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public int executeUpdate(String sql, int autoGeneratedKeys) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeUpdate(sql, autoGeneratedKeys);
+            }
+        };
+
+        Mockito.when(mockStatement.executeUpdate(sql, 
Statement.RETURN_GENERATED_KEYS))
+                .thenReturn(1);
+
+        int result = testProxy.executeUpdate(sql, 
Statement.RETURN_GENERATED_KEYS);
+
+        Assertions.assertEquals(1, result);
+        Mockito.verify(mockStatement).executeUpdate(sql, 
Statement.RETURN_GENERATED_KEYS);
+    }
+
+    @Test
+    public void testExecuteUpdateWithColumnIndexes() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+        int[] columnIndexes = {1};
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public int executeUpdate(String sql, int[] columnIndexes) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeUpdate(sql, columnIndexes);
+            }
+        };
+
+        Mockito.when(mockStatement.executeUpdate(sql, 
columnIndexes)).thenReturn(1);
+
+        int result = testProxy.executeUpdate(sql, columnIndexes);
+
+        Assertions.assertEquals(1, result);
+        Mockito.verify(mockStatement).executeUpdate(sql, columnIndexes);
+    }
+
+    @Test
+    public void testExecuteUpdateWithColumnNames() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+        String[] columnNames = {"id"};
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public int executeUpdate(String sql, String[] columnNames) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeUpdate(sql, columnNames);
+            }
+        };
+
+        Mockito.when(mockStatement.executeUpdate(sql, 
columnNames)).thenReturn(1);
+
+        int result = testProxy.executeUpdate(sql, columnNames);
+
+        Assertions.assertEquals(1, result);
+        Mockito.verify(mockStatement).executeUpdate(sql, columnNames);
+    }
+
+    @Test
+    public void testExecute() throws SQLException {
+        String sql = "SELECT * FROM test";
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public boolean execute(String sql) throws SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.execute(sql);
+            }
+        };
+
+        Mockito.when(mockStatement.execute(sql)).thenReturn(true);
+
+        boolean result = testProxy.execute(sql);
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).execute(sql);
+    }
+
+    @Test
+    public void testExecuteWithAutoGeneratedKeys() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public boolean execute(String sql, int autoGeneratedKeys) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.execute(sql, autoGeneratedKeys);
+            }
+        };
+
+        Mockito.when(mockStatement.execute(sql, 
Statement.RETURN_GENERATED_KEYS))
+                .thenReturn(true);
+
+        boolean result = testProxy.execute(sql, 
Statement.RETURN_GENERATED_KEYS);
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).execute(sql, 
Statement.RETURN_GENERATED_KEYS);
+    }
+
+    @Test
+    public void testExecuteWithColumnIndexes() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+        int[] columnIndexes = {1};
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public boolean execute(String sql, int[] columnIndexes) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.execute(sql, columnIndexes);
+            }
+        };
+
+        Mockito.when(mockStatement.execute(sql, 
columnIndexes)).thenReturn(true);
+
+        boolean result = testProxy.execute(sql, columnIndexes);
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).execute(sql, columnIndexes);
+    }
+
+    @Test
+    public void testExecuteWithColumnNames() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+        String[] columnNames = {"id"};
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public boolean execute(String sql, String[] columnNames) throws 
SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.execute(sql, columnNames);
+            }
+        };
+
+        Mockito.when(mockStatement.execute(sql, columnNames)).thenReturn(true);
+
+        boolean result = testProxy.execute(sql, columnNames);
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).execute(sql, columnNames);
+    }
+
+    @Test
+    public void testExecuteQuery() throws SQLException {
+        String sql = "SELECT * FROM test";
+        ResultSet mockResultSet = Mockito.mock(ResultSet.class);
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public ResultSet executeQuery(String sql) throws SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeQuery(sql);
+            }
+        };
+
+        
Mockito.when(mockStatement.executeQuery(sql)).thenReturn(mockResultSet);
+
+        ResultSet result = testProxy.executeQuery(sql);
+
+        Assertions.assertEquals(mockResultSet, result);
+        Mockito.verify(mockStatement).executeQuery(sql);
+    }
+
+    @Test
+    public void testExecuteBatch() throws SQLException {
+        int[] mockBatchResult = {1, 1, 1};
+
+        // Create a test implementation that we can control
+        StatementProxyXA testProxy = new 
StatementProxyXA(mockConnectionProxyXA, mockStatement) {
+            @Override
+            public int[] executeBatch() throws SQLException {
+                // Directly call the target statement for testing
+                return mockStatement.executeBatch();
+            }
+        };
+
+        Mockito.when(mockStatement.executeBatch()).thenReturn(mockBatchResult);
+
+        int[] result = testProxy.executeBatch();
+
+        Assertions.assertArrayEquals(mockBatchResult, result);
+        Mockito.verify(mockStatement).executeBatch();
+    }
+
+    @Test
+    public void testClose() throws SQLException {
+        statementProxyXA.close();
+
+        Mockito.verify(mockStatement).close();
+    }
+
+    @Test
+    public void testGetMaxFieldSize() throws SQLException {
+        Mockito.when(mockStatement.getMaxFieldSize()).thenReturn(100);
+
+        int result = statementProxyXA.getMaxFieldSize();
+
+        Assertions.assertEquals(100, result);
+        Mockito.verify(mockStatement).getMaxFieldSize();
+    }
+
+    @Test
+    public void testSetMaxFieldSize() throws SQLException {
+        statementProxyXA.setMaxFieldSize(200);
+
+        Mockito.verify(mockStatement).setMaxFieldSize(200);
+    }
+
+    @Test
+    public void testGetMaxRows() throws SQLException {
+        Mockito.when(mockStatement.getMaxRows()).thenReturn(1000);
+
+        int result = statementProxyXA.getMaxRows();
+
+        Assertions.assertEquals(1000, result);
+        Mockito.verify(mockStatement).getMaxRows();
+    }
+
+    @Test
+    public void testSetMaxRows() throws SQLException {
+        statementProxyXA.setMaxRows(2000);
+
+        Mockito.verify(mockStatement).setMaxFieldSize(2000); // Note: there's 
a bug in the original code
+    }
+
+    @Test
+    public void testSetEscapeProcessing() throws SQLException {
+        statementProxyXA.setEscapeProcessing(true);
+
+        Mockito.verify(mockStatement).setEscapeProcessing(true);
+    }
+
+    @Test
+    public void testGetQueryTimeout() throws SQLException {
+        Mockito.when(mockStatement.getQueryTimeout()).thenReturn(30);
+
+        int result = statementProxyXA.getQueryTimeout();
+
+        Assertions.assertEquals(30, result);
+        Mockito.verify(mockStatement).getQueryTimeout();
+    }
+
+    @Test
+    public void testSetQueryTimeout() throws SQLException {
+        statementProxyXA.setQueryTimeout(60);
+
+        Mockito.verify(mockStatement).setQueryTimeout(60);
+    }
+
+    @Test
+    public void testCancel() throws SQLException {
+        statementProxyXA.cancel();
+
+        Mockito.verify(mockStatement).cancel();
+    }
+
+    @Test
+    public void testGetWarnings() throws SQLException {
+        SQLWarning mockWarning = Mockito.mock(SQLWarning.class);
+        Mockito.when(mockStatement.getWarnings()).thenReturn(mockWarning);
+
+        SQLWarning result = statementProxyXA.getWarnings();
+
+        Assertions.assertEquals(mockWarning, result);
+        Mockito.verify(mockStatement).getWarnings();
+    }
+
+    @Test
+    public void testClearWarnings() throws SQLException {
+        statementProxyXA.clearWarnings();
+
+        Mockito.verify(mockStatement).clearWarnings();
+    }
+
+    @Test
+    public void testSetCursorName() throws SQLException {
+        statementProxyXA.setCursorName("cursor1");
+
+        Mockito.verify(mockStatement).setCursorName("cursor1");
+    }
+
+    @Test
+    public void testGetResultSet() throws SQLException {
+        ResultSet mockResultSet = Mockito.mock(ResultSet.class);
+        Mockito.when(mockStatement.getResultSet()).thenReturn(mockResultSet);
+
+        ResultSet result = statementProxyXA.getResultSet();
+
+        Assertions.assertEquals(mockResultSet, result);
+        Mockito.verify(mockStatement).getResultSet();
+    }
+
+    @Test
+    public void testGetUpdateCount() throws SQLException {
+        Mockito.when(mockStatement.getUpdateCount()).thenReturn(5);
+
+        int result = statementProxyXA.getUpdateCount();
+
+        Assertions.assertEquals(5, result);
+        Mockito.verify(mockStatement).getUpdateCount();
+    }
+
+    @Test
+    public void testGetMoreResults() throws SQLException {
+        Mockito.when(mockStatement.getMoreResults()).thenReturn(true);
+
+        boolean result = statementProxyXA.getMoreResults();
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).getMoreResults();
+    }
+
+    @Test
+    public void testSetFetchDirection() throws SQLException {
+        statementProxyXA.setFetchDirection(ResultSet.FETCH_FORWARD);
+
+        
Mockito.verify(mockStatement).setFetchDirection(ResultSet.FETCH_FORWARD);
+    }
+
+    @Test
+    public void testGetFetchDirection() throws SQLException {
+        
Mockito.when(mockStatement.getFetchDirection()).thenReturn(ResultSet.FETCH_FORWARD);
+
+        int result = statementProxyXA.getFetchDirection();
+
+        Assertions.assertEquals(ResultSet.FETCH_FORWARD, result);
+        Mockito.verify(mockStatement).getFetchDirection();
+    }
+
+    @Test
+    public void testSetFetchSize() throws SQLException {
+        statementProxyXA.setFetchSize(100);
+
+        Mockito.verify(mockStatement).setFetchSize(100);
+    }
+
+    @Test
+    public void testGetFetchSize() throws SQLException {
+        Mockito.when(mockStatement.getFetchSize()).thenReturn(100);
+
+        int result = statementProxyXA.getFetchSize();
+
+        Assertions.assertEquals(100, result);
+        Mockito.verify(mockStatement).getFetchSize();
+    }
+
+    @Test
+    public void testGetResultSetConcurrency() throws SQLException {
+        
Mockito.when(mockStatement.getResultSetConcurrency()).thenReturn(ResultSet.CONCUR_READ_ONLY);
+
+        int result = statementProxyXA.getResultSetConcurrency();
+
+        Assertions.assertEquals(ResultSet.CONCUR_READ_ONLY, result);
+        Mockito.verify(mockStatement).getResultSetConcurrency();
+    }
+
+    @Test
+    public void testGetResultSetType() throws SQLException {
+        
Mockito.when(mockStatement.getResultSetType()).thenReturn(ResultSet.TYPE_FORWARD_ONLY);
+
+        int result = statementProxyXA.getResultSetType();
+
+        Assertions.assertEquals(ResultSet.TYPE_FORWARD_ONLY, result);
+        Mockito.verify(mockStatement).getResultSetType();
+    }
+
+    @Test
+    public void testAddBatch() throws SQLException {
+        String sql = "INSERT INTO test (name) VALUES ('test')";
+        statementProxyXA.addBatch(sql);
+
+        Mockito.verify(mockStatement).addBatch(sql);
+    }
+
+    @Test
+    public void testClearBatch() throws SQLException {
+        statementProxyXA.clearBatch();
+
+        Mockito.verify(mockStatement).clearBatch();
+    }
+
+    @Test
+    public void testGetConnection() throws SQLException {
+        Connection mockConnection = Mockito.mock(Connection.class);
+        Mockito.when(mockStatement.getConnection()).thenReturn(mockConnection);
+
+        Connection result = statementProxyXA.getConnection();
+
+        Assertions.assertEquals(mockConnection, result);
+        Mockito.verify(mockStatement).getConnection();
+    }
+
+    @Test
+    public void testGetMoreResultsWithCurrent() throws SQLException {
+        
Mockito.when(mockStatement.getMoreResults(Statement.CLOSE_CURRENT_RESULT))
+                .thenReturn(true);
+
+        boolean result = 
statementProxyXA.getMoreResults(Statement.CLOSE_CURRENT_RESULT);
+
+        Assertions.assertTrue(result);
+        
Mockito.verify(mockStatement).getMoreResults(Statement.CLOSE_CURRENT_RESULT);
+    }
+
+    @Test
+    public void testGetGeneratedKeys() throws SQLException {
+        ResultSet mockResultSet = Mockito.mock(ResultSet.class);
+        
Mockito.when(mockStatement.getGeneratedKeys()).thenReturn(mockResultSet);
+
+        ResultSet result = statementProxyXA.getGeneratedKeys();
+
+        Assertions.assertEquals(mockResultSet, result);
+        Mockito.verify(mockStatement).getGeneratedKeys();
+    }
+
+    @Test
+    public void testGetResultSetHoldability() throws SQLException {
+        
Mockito.when(mockStatement.getResultSetHoldability()).thenReturn(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+
+        int result = statementProxyXA.getResultSetHoldability();
+
+        Assertions.assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, result);
+        Mockito.verify(mockStatement).getResultSetHoldability();
+    }
+
+    @Test
+    public void testIsClosed() throws SQLException {
+        Mockito.when(mockStatement.isClosed()).thenReturn(false);
+
+        boolean result = statementProxyXA.isClosed();
+
+        Assertions.assertFalse(result);
+        Mockito.verify(mockStatement).isClosed();
+    }
+
+    @Test
+    public void testSetPoolable() throws SQLException {
+        statementProxyXA.setPoolable(true);
+
+        Mockito.verify(mockStatement).setPoolable(true);
+    }
+
+    @Test
+    public void testIsPoolable() throws SQLException {
+        Mockito.when(mockStatement.isPoolable()).thenReturn(true);
+
+        boolean result = statementProxyXA.isPoolable();
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).isPoolable();
+    }
+
+    @Test
+    public void testCloseOnCompletion() throws SQLException {
+        statementProxyXA.closeOnCompletion();
+
+        Mockito.verify(mockStatement).closeOnCompletion();
+    }
+
+    @Test
+    public void testIsCloseOnCompletion() throws SQLException {
+        Mockito.when(mockStatement.isCloseOnCompletion()).thenReturn(true);
+
+        boolean result = statementProxyXA.isCloseOnCompletion();
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).isCloseOnCompletion();
+    }
+
+    @Test
+    public void testUnwrap() throws SQLException {
+        Mockito.when(mockStatement.unwrap(String.class)).thenReturn("test");
+
+        String result = statementProxyXA.unwrap(String.class);
+
+        Assertions.assertEquals("test", result);
+        Mockito.verify(mockStatement).unwrap(String.class);
+    }
+
+    @Test
+    public void testIsWrapperFor() throws SQLException {
+        
Mockito.when(mockStatement.isWrapperFor(String.class)).thenReturn(true);
+
+        boolean result = statementProxyXA.isWrapperFor(String.class);
+
+        Assertions.assertTrue(result);
+        Mockito.verify(mockStatement).isWrapperFor(String.class);
+    }
+}


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


Reply via email to