diff --git a/.gitignore b/.gitignore
index 9b00fbf..64ae211 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,5 +36,4 @@ application-local.yml
*.log
rebel.xml
FeignConfigTest.java
-test/
.DS_Store
\ No newline at end of file
diff --git a/axzo-test-spring-boot-starter/README.md b/axzo-test-spring-boot-starter/README.md
new file mode 100644
index 0000000..4e86f1c
--- /dev/null
+++ b/axzo-test-spring-boot-starter/README.md
@@ -0,0 +1,111 @@
+# axzo-test-spring-boot-starter
+
+单元测试支持库.
+更多细节用法请参考:
+- [Spring Testing](https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#testing)
+
+- [Spring Boot Testing](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing)
+## Quickstart
+### 1、引入依赖:
+
+``` xml
+
+
+ cn.axzo.framework
+ axzo-test-spring-boot-starter
+ 1.0.0-SNAPSHOT
+ test
+
+```
+### 2、Service单元测试实例
+``` java
+
+@SpringBootApplication(scanBasePackages = "cn.axzo")
+@EnableFeignClients(basePackages = "cn.axzo")
+public class WorkspaceServiceTest extends ServiceTestSupport {
+
+ @Autowired
+ private WorkspaceService service;
+
+ @MockBean
+ XxlJobConfig jobConfig;
+
+ @Test
+ void testQueryWorkspace() {
+ WorkspaceQueryReq query = WorkspaceQueryReq.enptyQuery();
+ IPage page = service.queryWorkspace(query);
+ page.getRecords().iterator().forEachRemaining(
+ workspace -> System.out.println(workspace)
+ );
+ }
+}
+```
+> @MockBean注解使用:
+```
+Mocks can be registered by type or by bean name. Any existing single bean of the same type defined in the context will be replaced by the mock. If no existing bean is defined a new one will be added.
+```
+### 3、Controller测试示例
+#### 3.1、 Post请求
+``` java
+@SpringBootApplication(scanBasePackages = "cn.axzo")
+@EnableFeignClients(basePackages = "cn.axzo")
+class WorkspaceApiImplTest extends ControllerTestSupport {
+
+ @Autowired
+ WorkspaceApiImpl api;
+
+ @MockBean
+ XxlJobConfig jobConfig;
+
+ @Override
+ protected Object getTestController() {
+ return api;
+ }
+
+ @Test
+ void testQueryWorkspace() throws Exception {
+ String url = "/api/workspace/queryWorkspace";
+ //设置请求参数
+ WorkspaceQueryReq query = WorkspaceQueryReq.enptyQuery();
+ query.setType(2);
+
+ doPostAction(url, query)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andReturn();
+ }
+
+}
+```
+#### 3.2 Get请求
+``` java
+@SpringBootApplication(scanBasePackages = "cn.axzo")
+@EnableFeignClients(basePackages = "cn.axzo")
+class ParticipatingUnitApiImplTest extends ControllerTestSupport {
+
+ @Autowired
+ ParticipatingUnitApiImpl api;
+
+ @Override
+ protected Object getTestController() {
+ return api;
+ }
+
+ @MockBean
+ XxlJobConfig jobConfig;
+
+ @Test
+ void testListByWorkspace() throws Exception {
+ Map params = new HashMap<>();
+ //设置请求参数
+ params.put("workspaceId", String.valueOf(23));
+
+ String url = "/api/workspace/participatingUnit/listByWorkspace";
+ doGetAction(url, params)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andReturn();
+ }
+
+}
+```
+### 4、编写Dao测试用例
+TODO
\ No newline at end of file
diff --git a/axzo-test-spring-boot-starter/pom.xml b/axzo-test-spring-boot-starter/pom.xml
new file mode 100644
index 0000000..2158e2c
--- /dev/null
+++ b/axzo-test-spring-boot-starter/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.13
+
+
+ cn.axzo.framework
+ axzo-test-spring-boot-starter
+ 1.0.0-SNAPSHOT
+ axzo-test-spring-boot-starter
+ 安心筑单元测试支持库
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ 3.0.7
+
+
+ org.springframework.boot
+ spring-boot-test
+
+
+ com.wix
+ wix-embedded-mysql
+ 4.6.2
+ true
+
+
+ org.apache.commons
+ commons-compress
+
+
+
+
+
+
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestConfiguration.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestConfiguration.java
new file mode 100644
index 0000000..dc85d4c
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestConfiguration.java
@@ -0,0 +1,36 @@
+package cn.axzo.framework.test;
+
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+@Configuration
+@EnableAutoConfiguration(exclude= {
+ MetricsAutoConfiguration.class,
+ UserDetailsServiceAutoConfiguration.class
+})
+public class ControllerTestConfiguration extends WebMvcConfigurationSupport{
+
+ /**
+ * 增加HttpMessageConverter,设置输出数据编码为UTF-8
+ */
+ @Bean
+ public HttpMessageConverter responseBodyConverter() {
+ return new StringHttpMessageConverter(Charset.forName("UTF-8"));
+ }
+
+ @Override
+ public void configureMessageConverters(List> converters) {
+ converters.add(responseBodyConverter());
+ addDefaultHttpMessageConverters(converters);
+ }
+}
+
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestSupport.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestSupport.java
new file mode 100644
index 0000000..38a6931
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ControllerTestSupport.java
@@ -0,0 +1,109 @@
+package cn.axzo.framework.test;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@ActiveProfiles({ "dev" })
+@SpringBootTest(classes = ControllerTestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
+public abstract class ControllerTestSupport {
+
+ public static final String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8";
+
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+ /**
+ * MockMvc模拟对象
+ */
+ protected MockMvc mockMvc;
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * 单元测试运行前环境、参数初始化
+ */
+ @BeforeEach
+ protected void setUp() throws Exception {
+ mockMvc = MockMvcBuilders.standaloneSetup(getTestController()).build();
+ }
+
+ /**
+ * 获取待测试Controller
+ * @return
+ */
+ protected abstract Object getTestController();
+
+ /**
+ * 发起POST请求
+ * @param url
+ * @param arg
+ * @return ResultActions
+ * @throws Exception
+ */
+ protected ResultActions doPostAction(String url,Object arg) throws Exception {
+ String contentJson = mapper.writeValueAsString(arg);
+ return mockMvc.perform(MockMvcRequestBuilders
+ .post(url)
+ .contentType(APPLICATION_JSON_UTF8)
+ .accept(APPLICATION_JSON_UTF8)
+ .content(contentJson))
+ .andDo(MockMvcResultHandlers.print());
+ }
+
+ /**
+ * 发起GET请求
+ * @param url
+ * @param arg
+ * @return ResultActions
+ * @throws Exception
+ */
+ protected ResultActions doGetAction(String url,MultiValueMap params) throws Exception {
+ return mockMvc.perform(MockMvcRequestBuilders
+ .get(url)
+ .contentType(APPLICATION_JSON_UTF8)
+ .accept(APPLICATION_JSON_UTF8)
+ .params(params))
+ .andDo(MockMvcResultHandlers.print());
+ }
+ /**
+ * 发起GET请求
+ * @param url
+ * @param arg
+ * @return ResultActions
+ * @throws Exception
+ */
+ protected ResultActions doGetAction(String url,Map params) throws Exception {
+ MultiValueMap multiValueMap = new LinkedMultiValueMap<>();
+ params.forEach((k,v)->{
+ multiValueMap.add(k, v);
+ });
+
+ return mockMvc.perform(MockMvcRequestBuilders
+ .get(url)
+ .contentType(APPLICATION_JSON_UTF8)
+ .accept(APPLICATION_JSON_UTF8)
+ .params(multiValueMap))
+ .andDo(MockMvcResultHandlers.print());
+ }
+
+ /**
+ * 单元测试运行后脏数据清理,对象关闭
+ */
+ @AfterEach
+ protected void tearDown() throws Exception {
+ }
+}
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestConfiguration.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestConfiguration.java
new file mode 100644
index 0000000..5d2be93
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestConfiguration.java
@@ -0,0 +1,13 @@
+package cn.axzo.framework.test;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration(exclude= {
+ MetricsAutoConfiguration.class
+})
+public class ServiceTestConfiguration {
+
+}
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestSupport.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestSupport.java
new file mode 100644
index 0000000..7bb5644
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/ServiceTestSupport.java
@@ -0,0 +1,31 @@
+package cn.axzo.framework.test;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.ActiveProfiles;
+
+@ActiveProfiles({"dev"})
+@SpringBootTest(classes = ServiceTestConfiguration.class,webEnvironment = WebEnvironment.MOCK)
+public class ServiceTestSupport {
+
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {
+ }
+
+}
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoComtroller.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoComtroller.java
new file mode 100644
index 0000000..27f6766
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoComtroller.java
@@ -0,0 +1,14 @@
+package cn.axzo.framework.test.demo;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class DemoComtroller {
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello";
+ }
+
+}
diff --git a/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoService.java b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoService.java
new file mode 100644
index 0000000..949cd52
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/java/cn/axzo/framework/test/demo/DemoService.java
@@ -0,0 +1,15 @@
+package cn.axzo.framework.test.demo;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * Demo演示
+ */
+@Service
+public class DemoService {
+
+ public Long plus(Long val1, Long val2) {
+ return val1 + val2;
+ }
+
+}
diff --git a/axzo-test-spring-boot-starter/src/main/resources/bootstrap.yml b/axzo-test-spring-boot-starter/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..f124825
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/resources/bootstrap.yml
@@ -0,0 +1,26 @@
+spring:
+ application:
+ name: unitest
+ cloud:
+ nacos:
+ config:
+ server-addr: ${NACOS_HOST:dev-nacos.axzo.cn}:${NACOS_PORT:80}
+# server-addr: ${NACOS_HOST:test-nacos.axzo.cn}:${NACOS_PORT:80}
+# server-addr: ${NACOS_HOST:test1-nacos.axzo.cn}:${NACOS_PORT:80}
+ file-extension: yaml
+ namespace: ${NACOS_NAMESPACE_ID:35eada10-9574-4db8-9fea-bc6a4960b6c7}
+# namespace: ${NACOS_NAMESPACE_ID:f3c0f0d2-bac4-4498-bee7-9c3636b3afdf}
+# namespace: ${NACOS_NAMESPACE_ID:6b278234-1409-4054-beb7-4bbc0def8e54}
+ prefix: ${spring.application.name}
+ profiles:
+ active: ${NACOS_PROFILES_ACTIVE:dev}
+# active: ${NACOS_PROFILES_ACTIVE:test}
+# active: ${NACOS_PROFILES_ACTIVE:test1}
+ main:
+ allow-bean-definition-overriding: true
+
+logging:
+ level:
+ com.alibaba.nacos.client.config.impl: WARN
+mybatis-plus:
+ type-enums-package: cn.axzo.apollo.server.enums,cn.axzo.apollo.core.enums,cn.axzo.apollo.order.enums
\ No newline at end of file
diff --git a/axzo-test-spring-boot-starter/src/main/resources/logback-spring.xml b/axzo-test-spring-boot-starter/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..791f80d
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/main/resources/logback-spring.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${PATTERN_DEFAULT}
+ utf-8
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoComtrollerTest.java b/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoComtrollerTest.java
new file mode 100644
index 0000000..49b0139
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoComtrollerTest.java
@@ -0,0 +1,40 @@
+package cn.axzo.framework.test.demo;
+
+import static org.hamcrest.CoreMatchers.containsString;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import cn.axzo.framework.test.ControllerTestSupport;
+
+
+@SpringBootApplication(scanBasePackages = "cn.axzo.framework.test.demo")
+@EnableFeignClients(basePackages = "cn.axzo.framework.test.demo")
+class DemoComtrollerTest extends ControllerTestSupport{
+
+
+ @Autowired
+ DemoComtroller api;
+
+ @Override
+ protected Object getTestController() {
+ return api;
+ }
+
+ @Test
+ void testHello() throws Exception {
+ String url = "/hello";
+ Map params = new HashMap<>();
+ doGetAction(url, params)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.content().string(containsString("Hello")))
+ .andReturn();
+ }
+
+}
diff --git a/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoServiceTest.java b/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoServiceTest.java
new file mode 100644
index 0000000..f2fb493
--- /dev/null
+++ b/axzo-test-spring-boot-starter/src/test/java/cn/axzo/framework/test/demo/DemoServiceTest.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package cn.axzo.framework.test.demo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+import cn.axzo.framework.test.ServiceTestSupport;
+
+@SpringBootApplication(scanBasePackages = "cn.axzo.framework.test.demo")
+@EnableFeignClients(basePackages = "cn.axzo.framework.test.demo")
+public class DemoServiceTest extends ServiceTestSupport{
+
+ @Autowired
+ private DemoService service;
+
+ @Test
+ void testPlus() {
+ assertEquals(2L, service.plus(1L, 1L));
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 3298e1a..7c40e34 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,7 @@
alarm-spring-boot-starter
canal-alarm
axzo-auth-spring-boot-starter
+ axzo-test-spring-boot-starter