feat: 修改包名 & 增加单元测试支持
This commit is contained in:
parent
e051c56112
commit
50a80ab86d
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.foundation.exception;
|
package cn.axzo.foundation.exception;
|
||||||
|
|
||||||
|
import cn.axzo.foundation.result.IResultCode;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package cn.axzo.foundation.exception;
|
package cn.axzo.foundation.exception;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.axzo.foundation.result.IResultCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
package cn.axzo.foundation.result;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ApiResult<T> {
|
||||||
|
private static final String SUCCESS_HTTP_CODE = "200";
|
||||||
|
private static final String FAILED_HTTP_CODE = "400";
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public static <T> ApiResult<T> success() {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ApiResult<T> success(T data) {
|
||||||
|
return ApiResult.<T>builder()
|
||||||
|
.code(SUCCESS_HTTP_CODE)
|
||||||
|
.data(data)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiResult error(String msg) {
|
||||||
|
return ApiResult.builder()
|
||||||
|
.code(FAILED_HTTP_CODE)
|
||||||
|
.msg(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiResult error(IResultCode resultCode) {
|
||||||
|
return error(resultCode.getErrorCode(), resultCode.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiResult error(String code, String msg) {
|
||||||
|
return ApiResult.builder()
|
||||||
|
.code(code)
|
||||||
|
.msg(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.foundation.exception;
|
package cn.axzo.foundation.result;
|
||||||
|
|
||||||
|
import cn.axzo.foundation.exception.BusinessException;
|
||||||
import cn.axzo.foundation.util.VarParamFormatter;
|
import cn.axzo.foundation.util.VarParamFormatter;
|
||||||
|
|
||||||
public interface IResultCode {
|
public interface IResultCode {
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package cn.axzo.foundation.result;
|
package cn.axzo.foundation.result;
|
||||||
|
|
||||||
import cn.axzo.foundation.exception.IResultCode;
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.converter;
|
package cn.axzo.foundation.dao.support.converter;
|
||||||
|
|
||||||
import cn.axzo.foundation.dao.support.data.mysql.MybatisPlusConverterUtils;
|
import cn.axzo.foundation.dao.support.mysql.MybatisPlusConverterUtils;
|
||||||
import cn.axzo.foundation.dao.support.data.page.IPageReq;
|
import cn.axzo.foundation.dao.support.page.IPageReq;
|
||||||
import cn.axzo.foundation.dao.support.data.page.PageResp;
|
import cn.axzo.foundation.dao.support.page.PageResp;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import cn.axzo.foundation.dao.support.data.mysql.type.SetTypeHandler;
|
import cn.axzo.foundation.dao.support.mysql.type.SetTypeHandler;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import cn.axzo.foundation.dao.support.data.page.IPageReq;
|
import cn.axzo.foundation.dao.support.page.IPageReq;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.SimpleWrapperConverter;
|
import cn.axzo.foundation.dao.support.wrapper.SimpleWrapperConverter;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import cn.axzo.foundation.exception.Axssert;
|
import cn.axzo.foundation.exception.Axssert;
|
||||||
import cn.axzo.foundation.result.ResultCode;
|
import cn.axzo.foundation.result.ResultCode;
|
||||||
@ -1,9 +1,9 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.CriteriaWrapper;
|
import cn.axzo.foundation.dao.support.wrapper.CriteriaWrapper;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.Operator;
|
import cn.axzo.foundation.dao.support.wrapper.Operator;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.OperatorProcessor;
|
import cn.axzo.foundation.dao.support.wrapper.OperatorProcessor;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.TriConsumer;
|
import cn.axzo.foundation.dao.support.wrapper.TriConsumer;
|
||||||
import cn.axzo.foundation.exception.Axssert;
|
import cn.axzo.foundation.exception.Axssert;
|
||||||
import cn.axzo.foundation.exception.BusinessException;
|
import cn.axzo.foundation.exception.BusinessException;
|
||||||
import cn.axzo.foundation.result.ResultCode;
|
import cn.axzo.foundation.result.ResultCode;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql;
|
package cn.axzo.foundation.dao.support.mysql;
|
||||||
|
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.CriteriaWrapper;
|
import cn.axzo.foundation.dao.support.wrapper.CriteriaWrapper;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.SimpleWrapperConverter;
|
import cn.axzo.foundation.dao.support.wrapper.SimpleWrapperConverter;
|
||||||
import cn.axzo.foundation.exception.Axssert;
|
import cn.axzo.foundation.exception.Axssert;
|
||||||
import cn.axzo.foundation.result.ResultCode;
|
import cn.axzo.foundation.result.ResultCode;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.plugins;
|
package cn.axzo.foundation.dao.support.mysql.plugins;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.plugins;
|
package cn.axzo.foundation.dao.support.mysql.plugins;
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.type;
|
package cn.axzo.foundation.dao.support.mysql.type;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.type;
|
package cn.axzo.foundation.dao.support.mysql.type;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.type;
|
package cn.axzo.foundation.dao.support.mysql.type;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.mysql.type;
|
package cn.axzo.foundation.dao.support.mysql.type;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.page;
|
package cn.axzo.foundation.dao.support.page;
|
||||||
|
|
||||||
import cn.axzo.foundation.enums.OrderEnum;
|
import cn.axzo.foundation.enums.OrderEnum;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.page;
|
package cn.axzo.foundation.dao.support.page;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.utils;
|
package cn.axzo.foundation.dao.support.utils;
|
||||||
|
|
||||||
import cn.axzo.foundation.enums.AppEnvEnum;
|
import cn.axzo.foundation.enums.AppEnvEnum;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.utils;
|
package cn.axzo.foundation.dao.support.utils;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import cn.axzo.foundation.dao.support.data.mysql.MybatisPlusConverterUtils;
|
import cn.axzo.foundation.dao.support.mysql.MybatisPlusConverterUtils;
|
||||||
import cn.axzo.foundation.dao.support.data.wrapper.SimpleWrapperConverter;
|
import cn.axzo.foundation.dao.support.wrapper.SimpleWrapperConverter;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@ -1,10 +1,9 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.FIELD})
|
@Target({ElementType.FIELD})
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableListMultimap;
|
import com.google.common.collect.ImmutableListMultimap;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
import cn.axzo.foundation.exception.BusinessException;
|
import cn.axzo.foundation.exception.BusinessException;
|
||||||
import cn.axzo.foundation.result.ResultCode;
|
import cn.axzo.foundation.result.ResultCode;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.foundation.dao.support.data.wrapper;
|
package cn.axzo.foundation.dao.support.wrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仅包内可访问
|
* 仅包内可访问
|
||||||
1
pom.xml
1
pom.xml
@ -23,6 +23,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>dao-support-lib</module>
|
<module>dao-support-lib</module>
|
||||||
<module>common-lib</module>
|
<module>common-lib</module>
|
||||||
|
<module>unittest-support-lib</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
90
unittest-support-lib/pom.xml
Normal file
90
unittest-support-lib/pom.xml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.axzo.foundation</groupId>
|
||||||
|
<artifactId>axzo-lib-box</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>unittest-support-lib</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.axzo.foundation</groupId>
|
||||||
|
<artifactId>common-lib</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 3rd -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>it.ozimov</groupId>
|
||||||
|
<artifactId>embedded-redis</artifactId>
|
||||||
|
<version>0.7.3</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,130 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support;
|
||||||
|
|
||||||
|
import cn.axzo.foundation.result.ApiResult;
|
||||||
|
import cn.axzo.foundation.unittest.support.config.MysqlConfig;
|
||||||
|
import cn.axzo.foundation.unittest.support.config.RedisConfig;
|
||||||
|
import cn.axzo.foundation.unittest.support.config.TestConfig;
|
||||||
|
import cn.axzo.foundation.unittest.support.config.TransactionalConfig;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.fastjson.TypeReference;
|
||||||
|
import com.google.common.collect.HashBasedTable;
|
||||||
|
import com.google.common.collect.Table;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import org.springframework.test.util.AopTestUtils;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||||
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ResourceUtils;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Import(value = {TestConfig.class, MysqlConfig.class, RedisConfig.class, TransactionalConfig.class})
|
||||||
|
@ContextConfiguration
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
@Transactional
|
||||||
|
@ActiveProfiles("unittest")
|
||||||
|
@ComponentScan("cn.axzo.**.config")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class BaseTest {
|
||||||
|
private static final String JSON_FILE_CLASSPATH = "classpath:json/";
|
||||||
|
/**
|
||||||
|
* 记录对象原始的 field 值. 因为这些值可能被mock替换, 在每次执行单元测试前统一进行一次替换恢复
|
||||||
|
* 避免影响后续的单元测试.
|
||||||
|
*/
|
||||||
|
private static Table<Object, String, Object> ORIGIN_FIELD_TABLE = HashBasedTable.create();
|
||||||
|
|
||||||
|
protected final MockMvc mockMvc;
|
||||||
|
|
||||||
|
protected final WebApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void teardown() {
|
||||||
|
// restore origin value of field.
|
||||||
|
ORIGIN_FIELD_TABLE.cellSet().stream().forEach(e -> {
|
||||||
|
ReflectionTestUtils.setField(e.getRowKey(), e.getColumnKey(), e.getValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T unwrapProxy(Object bean) {
|
||||||
|
return AopTestUtils.getUltimateTargetObject(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对象field为mock对象. teardown时恢复成原spring代理的对象
|
||||||
|
*/
|
||||||
|
protected void setMockField(Object targetObject, String fieldName, Object value) {
|
||||||
|
// 保存一份默认值
|
||||||
|
Object oldField = ReflectionTestUtils.getField(targetObject, fieldName);
|
||||||
|
ReflectionTestUtils.setField(targetObject, fieldName, value);
|
||||||
|
|
||||||
|
if (!ORIGIN_FIELD_TABLE.contains(targetObject, fieldName) && oldField != null) {
|
||||||
|
ORIGIN_FIELD_TABLE.put(targetObject, fieldName, oldField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MockHttpServletRequestBuilder buildJsonRequest(String path, Object object) {
|
||||||
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders
|
||||||
|
.post(path)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(JSONObject.toJSONString(object));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> ApiResult<T> getResult(MvcResult result, Class<T> clz) throws Exception {
|
||||||
|
return getResult(result, new TypeReference<ApiResult<T>>(clz) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> ApiResult<T> getResult(MvcResult result, TypeReference<ApiResult<T>> typeReference) throws Exception {
|
||||||
|
Assert.notNull(result, "Result must not be null");
|
||||||
|
String response = result.getResponse().getContentAsString();
|
||||||
|
return JSONObject.parseObject(response, typeReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T loadJson(String fileName, Class<T> clz) {
|
||||||
|
try {
|
||||||
|
String jsonString = Files.asCharSource(ResourceUtils.getFile(JSON_FILE_CLASSPATH + fileName), StandardCharsets.UTF_8).read();
|
||||||
|
return JSON.parseObject(jsonString, clz);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("loadJson got error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> loadJsonAsList(String fileName, Class<T> clz) {
|
||||||
|
try {
|
||||||
|
String jsonString = Files.asCharSource(ResourceUtils.getFile(JSON_FILE_CLASSPATH + fileName), StandardCharsets.UTF_8).read();
|
||||||
|
return JSONArray.parseArray(jsonString, clz);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("loadJsonAsList got error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果mysql/h2存在时增加的配置
|
||||||
|
* 1. 构造DataLoader
|
||||||
|
*/
|
||||||
|
@ConditionalOnClass({JdbcTemplate.class})
|
||||||
|
public class MysqlConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MysqlDataLoader mysqlDataLoader() {
|
||||||
|
return new MysqlDataLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql 测试数据加载
|
||||||
|
* <p>
|
||||||
|
* 测试数据后缀.sql, 默认加载 DEFAULT section 的数据. 如果需要加载指定section的数据需要带上sectionName
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 文件中通过 "#-->"来定义section. loader可以加载指定section的数据.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 文件路径: test/resources/mysql/${testClassName}.sql.
|
||||||
|
* <p>
|
||||||
|
* 数据格式如下
|
||||||
|
* <pre>
|
||||||
|
* #-->DEFAULT
|
||||||
|
* sql statement1;
|
||||||
|
* sql statement2;
|
||||||
|
*
|
||||||
|
* #-->section1
|
||||||
|
* sql statement3;
|
||||||
|
* sql statement4;
|
||||||
|
*
|
||||||
|
* #-->section2
|
||||||
|
* sql statement5;
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author chenjun
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class MysqlDataLoader {
|
||||||
|
|
||||||
|
private final static String MYSQL_DATA_PATH = "classpath:mysql/";
|
||||||
|
private final static String MYSQL_FILE_SUFFIX = ".sql";
|
||||||
|
private final static String DEFAULT_SECTION = "DEFAULT";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
private LoadingCache<File, Multimap<String, String>> sqlFileCaches = CacheBuilder.newBuilder()
|
||||||
|
.build(new CacheLoader<File, Multimap<String, String>>() {
|
||||||
|
@SuppressWarnings("NullableProblems")
|
||||||
|
public Multimap<String, String> load(File file) throws Exception {
|
||||||
|
List<String> lines = Files.asCharSource(file, Charset.forName("utf-8")).readLines();
|
||||||
|
String sectionFlag = "#-->";
|
||||||
|
Multimap<String, String> sections = LinkedListMultimap.create();
|
||||||
|
String currentSectionName = "";
|
||||||
|
// 按照section分组.
|
||||||
|
for (String line : lines) {
|
||||||
|
line = line.trim();
|
||||||
|
if (StringUtils.isAllBlank(line)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String sectionName = StringUtils.substringAfter(line, sectionFlag);
|
||||||
|
if (org.apache.logging.log4j.util.Strings.isNotBlank(sectionName)) {
|
||||||
|
currentSectionName = sectionName;
|
||||||
|
} else {
|
||||||
|
sections.put(currentSectionName, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public void loadFromClassName(String className) {
|
||||||
|
String locationPattern = MYSQL_DATA_PATH + className + MYSQL_FILE_SUFFIX;
|
||||||
|
File file = getFile(locationPattern);
|
||||||
|
execStatements(file, ImmutableList.of(DEFAULT_SECTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void loadFromClassName(String className, List<String> includeSections) {
|
||||||
|
String locationPattern = MYSQL_DATA_PATH + className + MYSQL_FILE_SUFFIX;
|
||||||
|
File file = getFile(locationPattern);
|
||||||
|
execStatements(file, includeSections);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String filePath) {
|
||||||
|
String locationPattern = MYSQL_DATA_PATH + filePath;
|
||||||
|
File file = getFile(locationPattern);
|
||||||
|
execStatements(file, ImmutableList.of(DEFAULT_SECTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String filePath, List<String> includeSections) {
|
||||||
|
String locationPattern = MYSQL_DATA_PATH + filePath;
|
||||||
|
File file = getFile(locationPattern);
|
||||||
|
execStatements(file, includeSections);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getFile(String locationPattern) {
|
||||||
|
File file;
|
||||||
|
try {
|
||||||
|
file = ResourceUtils.getFile(locationPattern);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException("try get file error", ex);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void execStatements(File file, List<String> includeSections) {
|
||||||
|
Multimap<String, String> sections = sqlFileCaches.getUnchecked(file);
|
||||||
|
List<String> statements = sections.entries().stream()
|
||||||
|
.filter(e -> includeSections.isEmpty() || includeSections.contains(e.getKey()))
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
String sql = Joiner.on("\n").join(statements);
|
||||||
|
log.info("\n>>>>>>>>>>>>>>> Execute SQL {}\n {}", Joiner.on(",").join(includeSections), sql);
|
||||||
|
jdbcTemplate.update(sql);
|
||||||
|
log.info("<<<<<<<<<<<<< Execute DONE\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import redis.embedded.RedisServer;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis存在时, 处理相关配置
|
||||||
|
* 1. 启动embedded的redis
|
||||||
|
*/
|
||||||
|
@ConditionalOnClass({RedisTemplate.class})
|
||||||
|
public class RedisConfig {
|
||||||
|
private RedisServer redisServer;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void postConstruct() {
|
||||||
|
redisServer = new RedisServer(16379);
|
||||||
|
// redis server会在后台启动一个redis server的进程,默认IP=127.0.0.1
|
||||||
|
redisServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void preDestroy() {
|
||||||
|
// 测试结束后必须调用redisServer.stop(), 否则后台运行的redis server进程会一直存在并占用6379端口
|
||||||
|
redisServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.config;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.core.task.SyncTaskExecutor;
|
||||||
|
import org.springframework.core.task.TaskExecutor;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class TestConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
public TaskExecutor mockTaskExecutor() {
|
||||||
|
return new SyncTaskExecutor();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
|
import org.springframework.transaction.TransactionException;
|
||||||
|
import org.springframework.transaction.TransactionManager;
|
||||||
|
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造TransactionManager
|
||||||
|
* 如果没有mysql/h2时 构造一个空的TransactionManager
|
||||||
|
*/
|
||||||
|
@ConditionalOnMissingClass(value = {"org.springframework.jdbc.core.JdbcTemplate"})
|
||||||
|
public class TransactionalConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TransactionManager transactionManager() {
|
||||||
|
return new AbstractPlatformTransactionManager() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doGetTransaction() throws TransactionException {
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBegin(Object o, TransactionDefinition transactionDefinition) throws TransactionException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doCommit(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRollback(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,271 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.h2;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.parser.Feature;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于支持h2兼容mysql中json的函数
|
||||||
|
* eg:
|
||||||
|
* CREATE ALIAS `JSON_EXTRACT` FOR "com.fiture.bfs.unittest.h2.JsonFunctions.extract";
|
||||||
|
* CREATE ALIAS `JSON_CONTAINS` FOR "com.fiture.bfs.unittest.h2.JsonFunctions.contains";
|
||||||
|
* CREATE ALIAS `JSON_LENGTH` FOR "com.fiture.bfs.unittest.h2.JsonFunctions.length";
|
||||||
|
*
|
||||||
|
* NOTE: JSON.parse(json, Feature.AutoCloseSource)其中Feature.AutoCloseSource是为了兼容fastjson2. 默认该feature在JSON中已经开启
|
||||||
|
*/
|
||||||
|
public class JsonFunctions {
|
||||||
|
/**
|
||||||
|
* 分割符号
|
||||||
|
*/
|
||||||
|
public static final String SEPARATOR = "\\.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根标识符名称
|
||||||
|
*/
|
||||||
|
public static final String ROOT_KEY_NAME = "$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组所有行下标符号
|
||||||
|
*/
|
||||||
|
public static final String ARRAY_ANY_INDEX = "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则表达式数组匹配模式
|
||||||
|
*/
|
||||||
|
public static final Pattern ARRAY_KEY_PATTERN = Pattern.compile("\\[ *(\\*|\\d+) *\\]");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据属性标识从对象中提取数据
|
||||||
|
*
|
||||||
|
* @param object 数据对象
|
||||||
|
* @param key 属性标识
|
||||||
|
* @return 值对象
|
||||||
|
*/
|
||||||
|
private static Object extract(Object object, Key key) {
|
||||||
|
if (object == null || key == null) {
|
||||||
|
return object;
|
||||||
|
} else if (key instanceof PropertyKey) {
|
||||||
|
String name = ((PropertyKey) key).name;
|
||||||
|
Object value =
|
||||||
|
ROOT_KEY_NAME.equals(name) ? object : object instanceof Map ? ((Map<?, ?>) object).get(name) : null;
|
||||||
|
return extract(value, key.next);
|
||||||
|
} else if (key instanceof ArrayKey && object instanceof List) {
|
||||||
|
List<?> list = (List<?>) object;
|
||||||
|
Integer index = ((ArrayKey) key).index;
|
||||||
|
return index == null ? list.stream().flatMap(o -> {
|
||||||
|
Object value = extract(o, key.next);
|
||||||
|
return value instanceof Collection ? ((Collection) value).stream() : Stream.of(value);
|
||||||
|
}).filter(Objects::nonNull).collect(Collectors.toList())
|
||||||
|
: list.size() < index + 1 ? null : extract(list.get(index), key.next);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定属性标识从JSON数据中抽取数据
|
||||||
|
*
|
||||||
|
* @param json JSON数据
|
||||||
|
* @param key 属性标识
|
||||||
|
* @return JSON数据结果
|
||||||
|
*/
|
||||||
|
public static String extract(String json, String key) {
|
||||||
|
Object value = extract(JSON.parse(json, Feature.AutoCloseSource), Key.parse(key));
|
||||||
|
return value == null ? null : convert2str(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果值转换。
|
||||||
|
* <p>解决字符串toJSON的时候被添加双引号的问题
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String convert2str(Object value) {
|
||||||
|
if (value instanceof Map || value instanceof Collection) {
|
||||||
|
return JSON.toJSONString(value);
|
||||||
|
} else {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定属性标识判断值是否在JSON数据中存在
|
||||||
|
*
|
||||||
|
* @param json JSON数据
|
||||||
|
* @param value 值
|
||||||
|
* @param key 属性标识
|
||||||
|
* @return 真假数字(true:1、false:0)
|
||||||
|
*/
|
||||||
|
public static int contains(String json, String value, String key) {
|
||||||
|
if (!StringUtils.isEmpty(json) && !StringUtils.isEmpty(value)) {
|
||||||
|
Object data = extract(JSON.parse(json, Feature.AutoCloseSource), Key.parse(key));
|
||||||
|
Object target = JSON.parse(value, Feature.AutoCloseSource);
|
||||||
|
return targetInJsonData(data, target);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定属性标识判断值是否在JSON数据中存在
|
||||||
|
*
|
||||||
|
* @param json JSON数据
|
||||||
|
* @param value 值
|
||||||
|
* @return 真假数字(true:1、false:0)
|
||||||
|
*/
|
||||||
|
public static int contains(String json, String value) {
|
||||||
|
if (!StringUtils.isEmpty(json) && !StringUtils.isEmpty(value)) {
|
||||||
|
Object data = JSON.parse(json, Feature.AutoCloseSource);
|
||||||
|
Object target = JSON.parse(value, Feature.AutoCloseSource);
|
||||||
|
return targetInJsonData(data, target);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int targetInJsonData(Object data, Object target) {
|
||||||
|
if (data instanceof List) {
|
||||||
|
return ((List<?>) data).stream().filter(Objects::nonNull).collect(Collectors.toSet())
|
||||||
|
.containsAll(target instanceof List
|
||||||
|
? ((List<?>) target).stream().filter(Objects::nonNull).collect(Collectors.toSet())
|
||||||
|
: Sets.newHashSet(target)) ? 1 : 0;
|
||||||
|
} else if (target instanceof List) {
|
||||||
|
return ((List<?>) target).contains(data) ? 1 : 0;
|
||||||
|
}
|
||||||
|
return data != null && target != null && Objects.equals(data, target) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除字符串双引号
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String unquote(String value) {
|
||||||
|
return StringUtils.isEmpty(value) ? value : value.replaceAll("\"", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取JSON数据长度
|
||||||
|
*
|
||||||
|
* @param json JSON字符串
|
||||||
|
* @return 长度
|
||||||
|
*/
|
||||||
|
public static Integer length(String json) {
|
||||||
|
Object object = JSON.parse(json, Feature.AutoCloseSource);
|
||||||
|
return object instanceof Map ? ((Map<?, ?>) object).size()
|
||||||
|
: object instanceof Collection ? ((Collection<?>) object).size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性标识
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
private static class Key {
|
||||||
|
/**
|
||||||
|
* 下一个标识
|
||||||
|
*/
|
||||||
|
private Key next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上一个标识
|
||||||
|
*/
|
||||||
|
private Key parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取跟标识
|
||||||
|
*
|
||||||
|
* @return 标识
|
||||||
|
*/
|
||||||
|
private Key getRoot() {
|
||||||
|
return this.parent == null ? this : this.parent.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性标识链最后追加属性标识
|
||||||
|
*
|
||||||
|
* @param key 追加的属性标识
|
||||||
|
* @return 最后的属性标识
|
||||||
|
*/
|
||||||
|
private Key append(Key key) {
|
||||||
|
Key last = this;
|
||||||
|
while (last.next != null) {
|
||||||
|
last = last.next;
|
||||||
|
}
|
||||||
|
last.setNext(key);
|
||||||
|
key.setParent(last);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性标识转换
|
||||||
|
*
|
||||||
|
* @param text 属性标识字符串形式
|
||||||
|
* @return 属性标识对象
|
||||||
|
*/
|
||||||
|
public static Key parse(String text) {
|
||||||
|
Key key = null;
|
||||||
|
if (!StringUtils.isEmpty(text == null ? null : text.trim())) {
|
||||||
|
for (String s : text.split(SEPARATOR)) {
|
||||||
|
String name = ARRAY_KEY_PATTERN.split(s = s.trim())[0];
|
||||||
|
PropertyKey property = PropertyKey.builder().name(name.trim()).build();
|
||||||
|
key = key == null ? property : key.append(property);
|
||||||
|
Matcher matcher = ARRAY_KEY_PATTERN.matcher(s);
|
||||||
|
while (matcher.find()) {
|
||||||
|
String group = matcher.group().trim();
|
||||||
|
String index = group.substring(1, group.length() - 1).trim();
|
||||||
|
key = key.append(ArrayKey.builder()
|
||||||
|
.index(ARRAY_ANY_INDEX.equals(index) ? null : Integer.parseInt(index)).build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key.getRoot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段属性标识
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
private static class PropertyKey extends Key {
|
||||||
|
/**
|
||||||
|
* 属性名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组属性标识
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
private static class ArrayKey extends Key {
|
||||||
|
/**
|
||||||
|
* 数组下标,如果为空则表示引用所有记录
|
||||||
|
*/
|
||||||
|
private Integer index;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package cn.axzo.foundation.unittest.support.h2;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于支持h2兼容mysql中string的函数
|
||||||
|
* eg:
|
||||||
|
* CREATE ALIAS FIND_IN_SET FOR "com.fiture.bfs.unittest.h2.StringFunctions.findInSet";
|
||||||
|
*/
|
||||||
|
public class StringFunctions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CREATE ALIAS FIND_IN_SET FOR "com.fiture.bfs.unittest.h2.StringFunctions.findInSet";
|
||||||
|
*/
|
||||||
|
public static Integer findInSet(String str, String strList) {
|
||||||
|
if (!Objects.isNull(str) && !Objects.isNull(strList)) {
|
||||||
|
return strList.isEmpty() ? 0 : Arrays.asList(strList.split(",")).indexOf(str) + 1;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user