This is an automated email from the ASF dual-hosted git repository.
jimin 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 6a417a7e4d test: add UT for rm.fence (#7731)
6a417a7e4d is described below
commit 6a417a7e4da958dca2f1606566dc0c5cd4b0b7ab
Author: maple <[email protected]>
AuthorDate: Mon Oct 27 11:22:05 2025 +0800
test: add UT for rm.fence (#7731)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 1 +
.../rm/fence/FenceLogCleanRunnableUnitTest.java | 165 ++++++++++++++++
.../seata/rm/fence/FenceLogIdentityTest.java | 192 +++++++++++++++++++
.../seata/rm/fence/SpringFenceConfigTest.java | 125 ++++++++++++
.../seata/rm/fence/SpringFenceHandlerUnitTest.java | 209 +++++++++++++++++++++
6 files changed, 693 insertions(+)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 5613384abf..c4929c3507 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -91,6 +91,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7725](https://github.com/apache/incubator-seata/pull/7725)] add UT for
compressor module
- [[#7718](https://github.com/apache/incubator-seata/pull/7718)] add UT for
config module
- [[#7723](https://github.com/apache/incubator-seata/pull/7723)] add UT for
fastjson2 to test PostgreSQL Array type
+- [[#7731](https://github.com/apache/incubator-seata/pull/7731)] add UT for
rm.fence
### refactor:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 5b71604880..85bb2600f4 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -90,6 +90,7 @@
- [[#7725](https://github.com/apache/incubator-seata/pull/7725)]
为compressor模块增加单测
- [[#7718](https://github.com/apache/incubator-seata/pull/7718)] 为config模块增加单测
- [[#7723](https://github.com/apache/incubator-seata/pull/7723)] 添加 fastjson2
的 UT 来测试 PostgreSQL 数组类型
+- [[#7731](https://github.com/apache/incubator-seata/pull/7731)]
为rm.fence模块添加单测
### refactor:
diff --git
a/spring/src/test/java/org/apache/seata/rm/fence/FenceLogCleanRunnableUnitTest.java
b/spring/src/test/java/org/apache/seata/rm/fence/FenceLogCleanRunnableUnitTest.java
new file mode 100644
index 0000000000..18c63b9d42
--- /dev/null
+++
b/spring/src/test/java/org/apache/seata/rm/fence/FenceLogCleanRunnableUnitTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.fence;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Constructor;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit tests for FenceLogCleanRunnable - Safe version without static field
modification
+ * This test class focuses on testing the inner class without polluting global
state
+ */
+@ExtendWith(MockitoExtension.class)
+public class FenceLogCleanRunnableUnitTest {
+
+ @Test
+ public void testFenceLogCleanRunnableExists() throws Exception {
+ // Test that the inner class exists
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ Class<?> cleanRunnableClass = null;
+
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogCleanRunnable".equals(innerClass.getSimpleName())) {
+ cleanRunnableClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(cleanRunnableClass, "FenceLogCleanRunnable inner class
should exist");
+ assertTrue(Runnable.class.isAssignableFrom(cleanRunnableClass),
"Should implement Runnable interface");
+ }
+
+ @Test
+ public void testFenceLogCleanRunnableInstantiation() throws Exception {
+ // Test that we can create instance of the inner class
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ Class<?> cleanRunnableClass = null;
+
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogCleanRunnable".equals(innerClass.getSimpleName())) {
+ cleanRunnableClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(cleanRunnableClass);
+
+ Constructor<?> constructor =
cleanRunnableClass.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ Object runnable = constructor.newInstance();
+
+ assertNotNull(runnable);
+ assertTrue(runnable instanceof Runnable);
+ }
+
+ @Test
+ public void testDeleteFenceMethodWithMockedStatic() {
+ // Test static deleteFence method safely using MockedStatic
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence("test-xid",
123L))
+ .thenReturn(true);
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence("fail-xid",
456L))
+ .thenReturn(false);
+
+ // Test successful deletion
+ boolean result1 = SpringFenceHandler.deleteFence("test-xid", 123L);
+ assertTrue(result1);
+
+ // Test failed deletion
+ boolean result2 = SpringFenceHandler.deleteFence("fail-xid", 456L);
+ assertFalse(result2);
+
+ // Verify method calls
+ mockedStatic.verify(() ->
SpringFenceHandler.deleteFence("test-xid", 123L));
+ mockedStatic.verify(() ->
SpringFenceHandler.deleteFence("fail-xid", 456L));
+ }
+ }
+
+ @Test
+ public void testDeleteFenceWithException() {
+ // Test exception handling in static deleteFence method
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence("error-xid",
789L))
+ .thenThrow(new RuntimeException("Database error"));
+
+ // Should throw exception as expected
+ assertThrows(RuntimeException.class, () -> {
+ SpringFenceHandler.deleteFence("error-xid", 789L);
+ });
+
+ mockedStatic.verify(() ->
SpringFenceHandler.deleteFence("error-xid", 789L));
+ }
+ }
+
+ @Test
+ public void testMultipleDeleteFenceCalls() {
+ // Test multiple static method calls in isolated environment
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence(anyString(),
anyLong()))
+ .thenReturn(true);
+
+ // Make multiple calls
+ boolean result1 = SpringFenceHandler.deleteFence("xid1", 100L);
+ boolean result2 = SpringFenceHandler.deleteFence("xid2", 200L);
+ boolean result3 = SpringFenceHandler.deleteFence("xid3", 300L);
+
+ // All should succeed
+ assertTrue(result1);
+ assertTrue(result2);
+ assertTrue(result3);
+
+ // Verify all calls were made
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("xid1",
100L));
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("xid2",
200L));
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("xid3",
300L));
+ }
+ }
+
+ @Test
+ public void testFenceLogIdentityInnerClass() throws Exception {
+ // Test FenceLogIdentity inner class existence and instantiation
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ Class<?> identityClass = null;
+
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogIdentity".equals(innerClass.getSimpleName())) {
+ identityClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(identityClass, "FenceLogIdentity inner class should
exist");
+
+ // Test instantiation
+ Constructor<?> constructor = identityClass.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ Object identity = constructor.newInstance();
+
+ assertNotNull(identity);
+ }
+}
diff --git
a/spring/src/test/java/org/apache/seata/rm/fence/FenceLogIdentityTest.java
b/spring/src/test/java/org/apache/seata/rm/fence/FenceLogIdentityTest.java
new file mode 100644
index 0000000000..85fe5e98d4
--- /dev/null
+++ b/spring/src/test/java/org/apache/seata/rm/fence/FenceLogIdentityTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.fence;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Constructor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * Unit tests for FenceLogIdentity
+ * Tests the inner class FenceLogIdentity of SpringFenceHandler
+ * This test class is completely isolated and safe from static state pollution
+ */
+public class FenceLogIdentityTest {
+
+ private Object fenceLogIdentity;
+ private Class<?> fenceLogIdentityClass;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ // Get inner class
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogIdentity".equals(innerClass.getSimpleName())) {
+ fenceLogIdentityClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(fenceLogIdentityClass, "FenceLogIdentity inner class
should exist");
+
+ // Create an instance
+ Constructor<?> constructor =
fenceLogIdentityClass.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ fenceLogIdentity = constructor.newInstance();
+ }
+
+ @Test
+ public void testDefaultConstructor() throws Exception {
+ // Given & When
+ Constructor<?> constructor =
fenceLogIdentityClass.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ Object instance = constructor.newInstance();
+
+ // Then
+ assertNotNull(instance);
+ }
+
+ @Test
+ public void testGetXidInitiallyNull() throws Exception {
+ // Given
+ java.lang.reflect.Method getXidMethod =
fenceLogIdentityClass.getDeclaredMethod("getXid");
+ getXidMethod.setAccessible(true);
+
+ // When
+ String xid = (String) getXidMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertNull(xid);
+ }
+
+ @Test
+ public void testGetBranchIdInitiallyNull() throws Exception {
+ // Given
+ java.lang.reflect.Method getBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("getBranchId");
+ getBranchIdMethod.setAccessible(true);
+
+ // When
+ Long branchId = (Long) getBranchIdMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertNull(branchId);
+ }
+
+ @Test
+ public void testSetAndGetXid() throws Exception {
+ // Given
+ String testXid = "test-xid-123";
+ java.lang.reflect.Method setXidMethod =
fenceLogIdentityClass.getDeclaredMethod("setXid", String.class);
+ java.lang.reflect.Method getXidMethod =
fenceLogIdentityClass.getDeclaredMethod("getXid");
+ setXidMethod.setAccessible(true);
+ getXidMethod.setAccessible(true);
+
+ // When
+ setXidMethod.invoke(fenceLogIdentity, testXid);
+ String result = (String) getXidMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertEquals(testXid, result);
+ }
+
+ @Test
+ public void testSetAndGetBranchId() throws Exception {
+ // Given
+ Long testBranchId = 123456L;
+ java.lang.reflect.Method setBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("setBranchId", Long.class);
+ java.lang.reflect.Method getBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("getBranchId");
+ setBranchIdMethod.setAccessible(true);
+ getBranchIdMethod.setAccessible(true);
+
+ // When
+ setBranchIdMethod.invoke(fenceLogIdentity, testBranchId);
+ Long result = (Long) getBranchIdMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertEquals(testBranchId, result);
+ }
+
+ @Test
+ public void testSetXidToNull() throws Exception {
+ // Given
+ java.lang.reflect.Method setXidMethod =
fenceLogIdentityClass.getDeclaredMethod("setXid", String.class);
+ java.lang.reflect.Method getXidMethod =
fenceLogIdentityClass.getDeclaredMethod("getXid");
+ setXidMethod.setAccessible(true);
+ getXidMethod.setAccessible(true);
+
+ // When
+ setXidMethod.invoke(fenceLogIdentity, (String) null);
+ String result = (String) getXidMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertNull(result);
+ }
+
+ @Test
+ public void testSetBranchIdToNull() throws Exception {
+ // Given
+ java.lang.reflect.Method setBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("setBranchId", Long.class);
+ java.lang.reflect.Method getBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("getBranchId");
+ setBranchIdMethod.setAccessible(true);
+ getBranchIdMethod.setAccessible(true);
+
+ // When
+ setBranchIdMethod.invoke(fenceLogIdentity, (Long) null);
+ Long result = (Long) getBranchIdMethod.invoke(fenceLogIdentity);
+
+ // Then
+ assertNull(result);
+ }
+
+ @Test
+ public void testSetAndGetMultipleValues() throws Exception {
+ // Given
+ String testXid1 = "test-xid-1";
+ String testXid2 = "test-xid-2";
+ Long testBranchId1 = 111L;
+ Long testBranchId2 = 222L;
+
+ java.lang.reflect.Method setXidMethod =
fenceLogIdentityClass.getDeclaredMethod("setXid", String.class);
+ java.lang.reflect.Method getXidMethod =
fenceLogIdentityClass.getDeclaredMethod("getXid");
+ java.lang.reflect.Method setBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("setBranchId", Long.class);
+ java.lang.reflect.Method getBranchIdMethod =
fenceLogIdentityClass.getDeclaredMethod("getBranchId");
+
+ setXidMethod.setAccessible(true);
+ getXidMethod.setAccessible(true);
+ setBranchIdMethod.setAccessible(true);
+ getBranchIdMethod.setAccessible(true);
+
+ // When & Then - Set first group of values
+ setXidMethod.invoke(fenceLogIdentity, testXid1);
+ setBranchIdMethod.invoke(fenceLogIdentity, testBranchId1);
+
+ assertEquals(testXid1, getXidMethod.invoke(fenceLogIdentity));
+ assertEquals(testBranchId1,
getBranchIdMethod.invoke(fenceLogIdentity));
+
+ // When & Then - Set second group of values
+ setXidMethod.invoke(fenceLogIdentity, testXid2);
+ setBranchIdMethod.invoke(fenceLogIdentity, testBranchId2);
+
+ assertEquals(testXid2, getXidMethod.invoke(fenceLogIdentity));
+ assertEquals(testBranchId2,
getBranchIdMethod.invoke(fenceLogIdentity));
+ }
+}
diff --git
a/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceConfigTest.java
b/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceConfigTest.java
new file mode 100644
index 0000000000..f1aeb24a1a
--- /dev/null
+++ b/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceConfigTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.fence;
+
+import org.apache.seata.common.exception.FrameworkErrorCode;
+import
org.apache.seata.integration.tx.api.fence.exception.CommonFenceException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import javax.sql.DataSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockStatic;
+
+/**
+ * Unit tests for SpringFenceConfig
+ * Uses MockedStatic to avoid static state pollution
+ * This version is completely isolated and safe from global test pollution
+ */
+@ExtendWith(MockitoExtension.class)
+public class SpringFenceConfigTest {
+
+ @Mock
+ private DataSource dataSource;
+
+ @Mock
+ private PlatformTransactionManager transactionManager;
+
+ private SpringFenceConfig springFenceConfig;
+
+ @BeforeEach
+ public void setUp() {
+ springFenceConfig = new SpringFenceConfig(dataSource,
transactionManager);
+ }
+
+ @Test
+ public void testConstructorWithValidParameters() {
+ // Given
+ DataSource testDataSource = dataSource;
+ PlatformTransactionManager testTransactionManager = transactionManager;
+
+ // When
+ SpringFenceConfig config = new SpringFenceConfig(testDataSource,
testTransactionManager);
+
+ // Then
+ assertNotNull(config);
+ }
+
+ @Test
+ public void
testAfterPropertiesSetWithValidDataSourceAndTransactionManager() {
+ // Given
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ // When
+ springFenceConfig.afterPropertiesSet();
+
+ // Then
+ mockedStatic.verify(() ->
SpringFenceHandler.setDataSource(dataSource));
+ mockedStatic.verify(() ->
SpringFenceHandler.setTransactionTemplate(any(TransactionTemplate.class)));
+ }
+ }
+
+ @Test
+ public void testAfterPropertiesSetWithNullDataSource() {
+ // Given
+ SpringFenceConfig configWithNullDataSource = new
SpringFenceConfig(null, transactionManager);
+
+ // When & Then
+ CommonFenceException exception =
assertThrows(CommonFenceException.class, () -> {
+ configWithNullDataSource.afterPropertiesSet();
+ });
+
+ assertEquals(FrameworkErrorCode.DateSourceNeedInjected,
exception.getErrcode());
+ }
+
+ @Test
+ public void testAfterPropertiesSetWithNullTransactionManager() {
+ // Given
+ SpringFenceConfig configWithNullTxManager = new
SpringFenceConfig(dataSource, null);
+
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ // When & Then
+ CommonFenceException exception =
assertThrows(CommonFenceException.class, () -> {
+ configWithNullTxManager.afterPropertiesSet();
+ });
+
+ assertEquals(FrameworkErrorCode.TransactionManagerNeedInjected,
exception.getErrcode());
+ }
+ }
+
+ @Test
+ public void testAfterPropertiesSetWithBothNullParameters() {
+ // Given
+ SpringFenceConfig configWithBothNull = new SpringFenceConfig(null,
null);
+
+ // When & Then
+ CommonFenceException exception =
assertThrows(CommonFenceException.class, () -> {
+ configWithBothNull.afterPropertiesSet();
+ });
+
+ assertEquals(FrameworkErrorCode.DateSourceNeedInjected,
exception.getErrcode());
+ }
+}
diff --git
a/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceHandlerUnitTest.java
b/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceHandlerUnitTest.java
new file mode 100644
index 0000000000..36e5c028d5
--- /dev/null
+++
b/spring/src/test/java/org/apache/seata/rm/fence/SpringFenceHandlerUnitTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.fence;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.sql.DataSource;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit tests for SpringFenceHandler - Safe version without static field
modification
+ * This test class focuses on testing methods that don't require static state
modification
+ */
+@ExtendWith(MockitoExtension.class)
+public class SpringFenceHandlerUnitTest {
+
+ @Mock
+ private DataSource dataSource;
+
+ private SpringFenceHandler springFenceHandler;
+
+ @BeforeEach
+ public void setUp() {
+ springFenceHandler = new SpringFenceHandler();
+ }
+
+ @Test
+ public void testSpringFenceHandlerInstantiation() {
+ // Test that SpringFenceHandler can be instantiated
+ SpringFenceHandler handler = new SpringFenceHandler();
+ assertNotNull(handler);
+ }
+
+ @Test
+ public void testCreateTransactionTemplateForTransactionalMethodWithNull()
throws Exception {
+ // Test private method through reflection without modifying static
state
+ Method createMethod = SpringFenceHandler.class.getDeclaredMethod(
+ "createTransactionTemplateForTransactionalMethod",
Transactional.class);
+ createMethod.setAccessible(true);
+
+ // Use MockedStatic to safely test without polluting global state
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class, CALLS_REAL_METHODS)) {
+ // Mock static method calls within this scope
+
mockedStatic.when(SpringFenceHandler::getDataSource).thenReturn(dataSource);
+
+ // This test will verify the method works with null transactional
annotation
+ // The actual implementation will be tested in integration tests
+ assertDoesNotThrow(() -> {
+ createMethod.invoke(springFenceHandler, (Transactional) null);
+ });
+ }
+ }
+
+ @Test
+ public void testCreateTransactionTemplateWithTransactionalAnnotation()
throws Exception {
+ // Test with dynamic proxy for Transactional annotation
+ Transactional transactional = (Transactional)
java.lang.reflect.Proxy.newProxyInstance(
+ Transactional.class.getClassLoader(), new Class[]
{Transactional.class}, (proxy, method, args) -> {
+ if ("isolation".equals(method.getName())) {
+ return Isolation.READ_COMMITTED;
+ }
+ return method.getDefaultValue();
+ });
+
+ Method createMethod = SpringFenceHandler.class.getDeclaredMethod(
+ "createTransactionTemplateForTransactionalMethod",
Transactional.class);
+ createMethod.setAccessible(true);
+
+ // Test that method works properly - need to handle potential
exceptions carefully
+ try {
+ Object result = createMethod.invoke(springFenceHandler,
transactional);
+ // The method should return a TransactionTemplate or throw an
exception
+ // We just verify that the invocation doesn't cause unexpected
errors
+ assertNotNull(result, "Method should return a result or throw a
specific exception");
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ // If the method throws an exception, it should be a known type
+ Throwable cause = e.getCause();
+ // For this test, we accept that the method might throw exceptions
due to missing dependencies
+ // The important thing is that the method is accessible and the
annotation is processed
+ assertTrue(
+ cause instanceof RuntimeException || cause instanceof
IllegalArgumentException,
+ "Expected runtime exception due to missing dependencies,
but got: "
+ + cause.getClass().getName());
+ }
+ }
+
+ @Test
+ public void testStaticMethodsWithMockedStatic() {
+ // Test static methods safely using MockedStatic
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+
mockedStatic.when(SpringFenceHandler::getDataSource).thenReturn(dataSource);
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence("test", 123L))
+ .thenReturn(true);
+
+ // Test static method calls within mocked scope
+ DataSource result = SpringFenceHandler.getDataSource();
+ boolean deleteResult = SpringFenceHandler.deleteFence("test",
123L);
+
+ assertSame(dataSource, result);
+ assertTrue(deleteResult);
+
+ // Verify interactions
+ mockedStatic.verify(SpringFenceHandler::getDataSource);
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("test",
123L));
+ }
+ // MockedStatic automatically restores original behavior after
try-with-resources
+ }
+
+ @Test
+ public void testMultipleStaticMethodCalls() {
+ // Test multiple static method calls in isolated scope
+ try (MockedStatic<SpringFenceHandler> mockedStatic =
mockStatic(SpringFenceHandler.class)) {
+ mockedStatic
+ .when(() -> SpringFenceHandler.deleteFence(anyString(),
anyLong()))
+ .thenReturn(true);
+
+ boolean result1 = SpringFenceHandler.deleteFence("xid1", 100L);
+ boolean result2 = SpringFenceHandler.deleteFence("xid2", 200L);
+
+ assertTrue(result1);
+ assertTrue(result2);
+
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("xid1",
100L));
+ mockedStatic.verify(() -> SpringFenceHandler.deleteFence("xid2",
200L));
+ }
+ }
+
+ @Test
+ public void testInstanceMethodsOnly() {
+ // Test that we can create instances without static dependency issues
+ SpringFenceHandler handler1 = new SpringFenceHandler();
+ SpringFenceHandler handler2 = new SpringFenceHandler();
+
+ assertNotNull(handler1);
+ assertNotNull(handler2);
+ assertNotSame(handler1, handler2);
+ }
+
+ @Test
+ public void testFenceLogIdentityInnerClass() throws Exception {
+ // Test the inner class without modifying static state
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ Class<?> fenceLogIdentityClass = null;
+
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogIdentity".equals(innerClass.getSimpleName())) {
+ fenceLogIdentityClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(fenceLogIdentityClass, "FenceLogIdentity inner class
should exist");
+
+ // Test that we can instantiate the inner class - need to make
constructor accessible
+ Constructor<?> constructor =
fenceLogIdentityClass.getDeclaredConstructor();
+ constructor.setAccessible(true); // Make private constructor accessible
+ Object identity = constructor.newInstance();
+ assertNotNull(identity);
+ }
+
+ @Test
+ public void testFenceLogCleanRunnableInnerClass() throws Exception {
+ // Test the inner class without modifying static state
+ Class<?>[] innerClasses =
SpringFenceHandler.class.getDeclaredClasses();
+ Class<?> cleanRunnableClass = null;
+
+ for (Class<?> innerClass : innerClasses) {
+ if ("FenceLogCleanRunnable".equals(innerClass.getSimpleName())) {
+ cleanRunnableClass = innerClass;
+ break;
+ }
+ }
+
+ assertNotNull(cleanRunnableClass, "FenceLogCleanRunnable inner class
should exist");
+
+ // Test that we can instantiate the inner class - need to make
constructor accessible
+ Constructor<?> constructor =
cleanRunnableClass.getDeclaredConstructor();
+ constructor.setAccessible(true); // Make private constructor accessible
+ Object runnable = constructor.newInstance();
+ assertNotNull(runnable);
+ assertTrue(runnable instanceof Runnable);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]