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 c90207648f test: add UT for seata-spring-boot-starter module (#7422)
c90207648f is described below

commit c90207648f2d2d048022399cd39a75e7f8b9810c
Author: OmCheeLin <[email protected]>
AuthorDate: Mon Jun 9 00:58:33 2025 +0800

    test: add UT for seata-spring-boot-starter module (#7422)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 seata-spring-boot-starter/pom.xml                  |  15 +++
 .../autoconfigure/SeataAutoConfigurationTest.java  |  89 ++++++++++++++
 .../SeataDataSourceAutoConfigurationTest.java      |  82 +++++++++++++
 .../SeataHttpAutoConfigurationTest.java            |  79 ++++++++++++
 .../SeataSagaAutoConfigurationTest.java            | 136 +++++++++++++++++++++
 7 files changed, 403 insertions(+)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 9f4217e1e2..d681aacc52 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -83,6 +83,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7359](https://github.com/apache/incubator-seata/issues/7359)] merge 
submodule test reports
 - [[#7377](https://github.com/apache/incubator-seata/issues/7377)] add UT for 
org.apache.seata.spring.annotation.scannercheckers
 - [[#7379](https://github.com/apache/incubator-seata/issues/7379)] add UT for 
TccAnnotationProcessor class
+- [[#7422](https://github.com/apache/incubator-seata/pull/7422)] add UT for 
seata-spring-boot-starter module
 
 
 ### refactor:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index a80d2b0d16..5d0a0c3908 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -84,6 +84,7 @@
 - [[#7359](https://github.com/apache/incubator-seata/issues/7359)] 
合并所有模块的单测报告,准确显示单测覆盖度
 - [[#7377](https://github.com/apache/incubator-seata/issues/7377)] 为 
org.apache.seata.spring.annotation.scannercheckers 添加单元测试
 - [[#7379](https://github.com/apache/incubator-seata/issues/7379)] 为 
TccAnnotationProcessor 添加了单元测试 
+- [[#7422](https://github.com/apache/incubator-seata/pull/7422)] 为 
seata-spring-boot-starter 添加了测试
 
 
 ### refactor:
diff --git a/seata-spring-boot-starter/pom.xml 
b/seata-spring-boot-starter/pom.xml
index 24f449166b..633686deb7 100644
--- a/seata-spring-boot-starter/pom.xml
+++ b/seata-spring-boot-starter/pom.xml
@@ -71,6 +71,21 @@
             <artifactId>rocketmq-client</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git 
a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java
 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java
new file mode 100644
index 0000000000..83423d87d1
--- /dev/null
+++ 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.spring.boot.autoconfigure;
+
+import org.apache.seata.spring.annotation.GlobalTransactionScanner;
+import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties;
+import org.apache.seata.tm.TMClient;
+import org.apache.seata.tm.api.DefaultFailureHandlerImpl;
+import org.apache.seata.tm.api.FailureHandler;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+
+/**
+ * Tests for {@link SeataAutoConfiguration} to verify conditional bean 
registration.
+ * Here not use new ApplicationContextRunner() to avoid environment to be null.
+ */
+@SpringBootTest(
+        classes = SeataAutoConfigurationTest.TestConfig.class,
+        properties = {
+                "seata.enabled=true",
+                "seata.application-id=testApp",
+                "seata.tx-service-group=test_tx_group"
+        }
+)
+public class SeataAutoConfigurationTest {
+
+    private static MockedStatic<TMClient> mockedTMClient;
+
+    @BeforeAll
+    static void mockStaticInit() {
+        mockedTMClient = Mockito.mockStatic(TMClient.class);
+        mockedTMClient.when(() -> TMClient.init(any(), any(), any(), 
any())).then(invocation -> null);
+    }
+
+    @AfterAll
+    static void closeMock() {
+        mockedTMClient.close();
+    }
+
+    @Configuration
+    @EnableConfigurationProperties(SeataProperties.class)
+    @ImportAutoConfiguration({SeataCoreAutoConfiguration.class, 
SeataAutoConfiguration.class})
+    static class TestConfig {
+    }
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Test
+    void testFailureHandlerBeanCreated() {
+        assertThat(applicationContext.containsBean("failureHandler")).isTrue();
+        FailureHandler failureHandler = 
applicationContext.getBean(FailureHandler.class);
+        assertThat(failureHandler).isNotNull();
+        
assertThat(failureHandler).isInstanceOf(DefaultFailureHandlerImpl.class);
+    }
+
+    @Test
+    void testGlobalTransactionScannerBeanCreated() {
+        
assertThat(applicationContext.containsBean("globalTransactionScanner")).isTrue();
+        GlobalTransactionScanner scanner = 
applicationContext.getBean(GlobalTransactionScanner.class);
+        assertThat(scanner).isNotNull();
+    }
+}
diff --git 
a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java
 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java
new file mode 100644
index 0000000000..5e1df4bad0
--- /dev/null
+++ 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.spring.boot.autoconfigure;
+
+import org.apache.seata.rm.datasource.DataSourceProxy;
+import 
org.apache.seata.spring.annotation.datasource.SeataAutoDataSourceProxyCreator;
+import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties;
+import 
org.apache.seata.spring.boot.autoconfigure.properties.SpringCloudAlibabaConfiguration;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import javax.sql.DataSource;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+
+/**
+ * Tests for {@link SeataDataSourceAutoConfiguration} to verify conditional 
bean registration.
+ */
+public class SeataDataSourceAutoConfigurationTest {
+    private final ApplicationContextRunner contextRunner = new 
ApplicationContextRunner()
+            
.withConfiguration(AutoConfigurations.of(SeataDataSourceAutoConfiguration.class))
+            .withBean(DataSource.class, () -> mock(DataSource.class))
+            .withBean(SeataProperties.class, SeataProperties::new)
+            .withBean(SpringCloudAlibabaConfiguration.class, 
SpringCloudAlibabaConfiguration::new);
+
+    @Test
+    void whenConditionsMet_thenAutoDataSourceProxyCreatorCreated() {
+        try (MockedConstruction<DataSourceProxy> mocked = 
mockConstruction(DataSourceProxy.class)) {
+            contextRunner
+                    .withPropertyValues(
+                            "seata.enabled=true",
+                            "seata.enableAutoDataSourceProxy=true",
+                            "seata.enable-auto-data-source-proxy=true"
+                    )
+                    .run(context -> {
+                        // assert DataSourceProxy construction to be mock
+                        assertThat(mocked.constructed()).isNotEmpty();
+                        
assertThat(context).hasSingleBean(SeataAutoDataSourceProxyCreator.class);
+                    });
+        }
+    }
+
+    @Test
+    void whenDisabledByProperty_thenBeanNotCreated() {
+        contextRunner
+                .withPropertyValues(
+                        "seata.enabled=false"
+                )
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(SeataAutoDataSourceProxyCreator.class);
+                });
+    }
+
+    @Test
+    void whenNoDataSourceBean_thenBeanNotCreated() {
+        new ApplicationContextRunner()
+                
.withConfiguration(AutoConfigurations.of(SeataDataSourceAutoConfiguration.class))
+                .withBean(SeataProperties.class, SeataProperties::new)
+                .withBean(SpringCloudAlibabaConfiguration.class, 
SpringCloudAlibabaConfiguration::new)
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(SeataAutoDataSourceProxyCreator.class);
+                });
+    }
+}
diff --git 
a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataHttpAutoConfigurationTest.java
 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataHttpAutoConfigurationTest.java
new file mode 100644
index 0000000000..f0cd6999a8
--- /dev/null
+++ 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataHttpAutoConfigurationTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.spring.boot.autoconfigure;
+
+import org.apache.seata.integration.http.JakartaSeataWebMvcConfigurer;
+import org.apache.seata.integration.http.SeataWebMvcConfigurer;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import 
org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+
+import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.HTTP_PREFIX;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link SeataHttpAutoConfiguration} to verify conditional bean 
registration.
+ */
+public class SeataHttpAutoConfigurationTest {
+    // No thread safety issues, no need to create in @BeforeEach
+    private final WebApplicationContextRunner webContextRunner = new 
WebApplicationContextRunner()
+            
.withConfiguration(AutoConfigurations.of(SeataHttpAutoConfiguration.class));
+    private final ApplicationContextRunner contextRunner = new 
ApplicationContextRunner()
+            
.withConfiguration(AutoConfigurations.of(SeataHttpAutoConfiguration.class));
+
+    @Test
+    void whenNotWebApplication_thenNoBeansCreated() {
+        contextRunner
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(SeataWebMvcConfigurer.class);
+                    
assertThat(context).doesNotHaveBean(JakartaSeataWebMvcConfigurer.class);
+                });
+    }
+
+    @Test
+    void whenInterceptorDisabled_thenNoBeansCreated() {
+        webContextRunner
+                .withPropertyValues(HTTP_PREFIX + ".interceptor-enabled=false")
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(SeataWebMvcConfigurer.class);
+                    
assertThat(context).doesNotHaveBean(JakartaSeataWebMvcConfigurer.class);
+                });
+    }
+
+    @Test
+    void whenJakartaClassMissing_thenCreatesSeataWebMvcConfigurer() {
+        webContextRunner
+                .withClassLoader(new 
FilteredClassLoader("jakarta.servlet.http.HttpServletRequest"))
+                .run(context -> {
+                    
assertThat(context).hasSingleBean(SeataWebMvcConfigurer.class);
+                    
assertThat(context).doesNotHaveBean(JakartaSeataWebMvcConfigurer.class);
+                });
+    }
+
+    @Test
+    void whenJakartaClassPresent_thenCreatesJakartaSeataWebMvcConfigurer() {
+        webContextRunner
+                .run(context -> {
+                    // Do not use 
assertThat(context).doesNotHaveBean(SeataWebMvcConfigurer.class),
+                    // because JakartaSeataWebMvcConfigurer extends 
SeataWebMvcConfigurer.
+                    
assertThat(context.getBeansOfType(SeataWebMvcConfigurer.class).values())
+                            
.hasOnlyElementsOfType(JakartaSeataWebMvcConfigurer.class);
+                });
+    }
+}
diff --git 
a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java
 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java
new file mode 100644
index 0000000000..96fc562555
--- /dev/null
+++ 
b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.spring.boot.autoconfigure;
+
+import org.apache.seata.core.model.Resource;
+import org.apache.seata.rm.DefaultResourceManager;
+import org.apache.seata.saga.engine.StateMachineConfig;
+import org.apache.seata.saga.engine.StateMachineEngine;
+import org.apache.seata.saga.engine.config.DbStateMachineConfig;
+import org.apache.seata.saga.engine.impl.ProcessCtrlStateMachineEngine;
+import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties;
+import org.apache.seata.tm.TMClient;
+import org.assertj.core.api.AssertionsForClassTypes;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import static 
org.apache.seata.spring.boot.autoconfigure.SeataSagaAutoConfiguration.SAGA_ASYNC_THREAD_POOL_EXECUTOR_BEAN_NAME;
+import static 
org.apache.seata.spring.boot.autoconfigure.SeataSagaAutoConfiguration.SAGA_REJECTED_EXECUTION_HANDLER_BEAN_NAME;
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link SeataSagaAutoConfiguration} to verify conditional bean 
registration.
+ */
+@SpringBootTest(
+        classes = {
+                SeataSagaAutoConfigurationTest.TestConfig.class
+        },
+        properties = {
+                "seata.enabled=true",
+                "seata.saga.enabled=true",
+                "spring.application.name=testApp",
+                "seata.tx-service-group=testTxGroup",
+                "seata.saga.state-machine.enable-async=true"
+        })
+class SeataSagaAutoConfigurationTest {
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    private static MockedStatic<TMClient> mockedTMClient;
+
+    private static MockedStatic<DefaultResourceManager> 
mockedDefaultResourceManager;
+
+    @Autowired(required = false)
+    @Qualifier(SAGA_ASYNC_THREAD_POOL_EXECUTOR_BEAN_NAME)
+    private ThreadPoolExecutor asyncExecutor;
+
+    @Autowired(required = false)
+    @Qualifier(SAGA_REJECTED_EXECUTION_HANDLER_BEAN_NAME)
+    private RejectedExecutionHandler rejectedExecutionHandler;
+
+    @BeforeAll
+    static void mockStaticInit() {
+        mockedTMClient = Mockito.mockStatic(TMClient.class);
+        mockedTMClient.when(() -> TMClient.init(any(), any(), any(), 
any())).then(invocation -> null);
+        mockedDefaultResourceManager = 
Mockito.mockStatic(DefaultResourceManager.class);
+        DefaultResourceManager mockResourceManager = 
mock(DefaultResourceManager.class);
+        doAnswer(invocation -> 
null).when(mockResourceManager).registerResource(any(Resource.class));
+        
mockedDefaultResourceManager.when(DefaultResourceManager::get).thenReturn(mockResourceManager);
+    }
+
+    @AfterAll
+    static void closeMock() {
+        mockedTMClient.close();
+        mockedDefaultResourceManager.close();
+    }
+
+    @Configuration
+    @EnableConfigurationProperties(SeataProperties.class)
+    @ImportAutoConfiguration({DataSourceAutoConfiguration.class, 
SeataCoreAutoConfiguration.class, SeataAutoConfiguration.class, 
SeataSagaAutoConfiguration.class})
+    static class TestConfig {
+        @Bean
+        public DataSource dataSource() throws SQLException {
+            Connection mockConnection = mock(Connection.class);
+            DatabaseMetaData metaData = mock(DatabaseMetaData.class);
+            when(mockConnection.getMetaData()).thenReturn(metaData);
+            DataSource mockDataSource = mock(DataSource.class);
+            when(mockDataSource.getConnection()).thenReturn(mockConnection);
+            return mockDataSource;
+        }
+    }
+
+    @Test
+    void testDbStateMachineConfigAndEngineBeanCreation() {
+        StateMachineConfig stateMachineConfig = 
applicationContext.getBean(StateMachineConfig.class);
+        AssertionsForClassTypes.assertThat(stateMachineConfig).isNotNull();
+        
assertThat(stateMachineConfig).isInstanceOf(DbStateMachineConfig.class);
+
+        StateMachineEngine stateMachineEngine = 
applicationContext.getBean(StateMachineEngine.class);
+        AssertionsForClassTypes.assertThat(stateMachineEngine).isNotNull();
+        
assertThat(stateMachineEngine).isInstanceOf(ProcessCtrlStateMachineEngine.class);
+    }
+
+    @Test
+    void testAsyncThreadPoolExecutorCreation() {
+        assertThat(asyncExecutor).isNotNull();
+        assertThat(rejectedExecutionHandler).isNotNull();
+        
assertThat(rejectedExecutionHandler).isInstanceOf(ThreadPoolExecutor.CallerRunsPolicy.class);
+    }
+}


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

Reply via email to