Merge branch 'new_3A' of axzsource.com:infra/axzo-framework into new_3A

This commit is contained in:
Gao Wei 2022-07-07 22:04:44 +08:00
commit 9d8edff9db
14 changed files with 520 additions and 1 deletions

1
.gitignore vendored
View File

@ -36,5 +36,4 @@ application-local.yml
*.log
rebel.xml
FeignConfigTest.java
test/
.DS_Store

View File

@ -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
<!-- 单元测试依赖 -->
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-test-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
```
### 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<Workspace> 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<String,String> 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

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.13</version>
<relativePath/>
</parent>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-test-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>axzo-test-spring-boot-starter</name>
<description>安心筑单元测试支持库</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>com.wix</groupId>
<artifactId>wix-embedded-mysql</artifactId>
<version>4.6.2</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -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<String> responseBodyConverter() {
return new StringHttpMessageConverter(Charset.forName("UTF-8"));
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(responseBodyConverter());
addDefaultHttpMessageConverters(converters);
}
}

View File

@ -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<String,String> 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<String,String> params) throws Exception {
MultiValueMap<String,String> 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 {
}
}

View File

@ -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 {
}

View File

@ -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 {
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,27 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 变量 yudao.info.base-package基础业务包 -->
<springProperty scope="context" name="appName" source="spring.application.name"/>
<!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%thread] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<property name="LOG_FILE" value="target/${appName}.log"/>
<!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${PATTERN_DEFAULT}</pattern>
<charset>utf-8</charset>
</encoder>    
</appender>
<!-- 本地环境 -->
<springProfile name="local,dev,test,unitest">
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>

View File

@ -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<String,String> params = new HashMap<>();
doGetAction(url, params)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string(containsString("Hello")))
.andReturn();
}
}

View File

@ -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));
}
}

View File

@ -18,6 +18,7 @@
<module>alarm-spring-boot-starter</module>
<module>canal-alarm</module>
<module>axzo-auth-spring-boot-starter</module>
<module>axzo-test-spring-boot-starter</module>
</modules>
<build>