├── .gitattributes ├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── encodings.xml ├── misc.xml └── vcs.xml ├── Dockerfile ├── README.md ├── allure-results ├── 04254a7b-6cfa-45dd-bcc8-b6e9fffc0575-container.json ├── 047586f6-20d3-40c5-bc19-a7c22396890f-container.json ├── 09d3a09f-7b79-4883-a688-d91189ec1500-container.json ├── 1c8bd668-f52b-4b79-8444-48231ffef5d4-container.json ├── 24a8d093-bf10-4512-8c3c-be02defe92f0-result.json ├── 277427b6-6ec7-41f7-8ea4-4f49223d04bc-container.json ├── 28f33310-3b0c-4d92-a709-89c3c18c482c-container.json ├── 295a76f3-cf06-4cd8-b05b-6099cc3a5c2b-result.json ├── 2a612220-49ef-4e1d-9bcc-2e9a2e4dd0b4-result.json ├── 2e4aa861-8a82-4687-8e98-8634967b3445-container.json ├── 349b293e-e3f7-4ecb-9c1c-5ca9329776b2-container.json ├── 4718a26e-2d86-495f-8566-7269e150b666-container.json ├── 4a8a4f53-5975-4c41-bb0b-f56209d8a85d-container.json ├── 57fe5ed7-b155-4762-907a-b931eed869a7-container.json ├── 7271ebb1-f987-409e-91ea-2bc4f275cc12-container.json ├── 77d30321-4250-4ace-b403-01504dcfc6d2-container.json ├── 8aacbeb5-5ba6-4aca-946c-f7ade72411d6-result.json ├── 9632b653-fbeb-4baa-a6ac-ceb73b13008c-container.json ├── a1e93c62-ede2-445b-bd5a-1c1eae4f9ffd-container.json ├── ca0d5021-bc46-4670-a63d-5790bf49cd50-container.json ├── ce62675b-5caf-4262-b409-ea3bbfe266d8-container.json ├── e9977e95-297b-499c-aa8d-87d0e7c00602-container.json ├── f723aea0-c711-4bf0-a2ea-8c868420050c-result.json └── f907ec45-a992-46d3-a226-9b3920083580-result.json ├── database └── javaelf_init.sql ├── docker-auto.sh ├── pom.xml └── src ├── main ├── java │ ├── com │ │ └── javaelf │ │ │ ├── JavaElfApplication.java │ │ │ ├── base │ │ │ └── TestBase.java │ │ │ ├── controller │ │ │ └── TestResultsController.java │ │ │ ├── dao │ │ │ ├── InterfaceMsgDao.java │ │ │ ├── TestCaseDao.java │ │ │ └── VariableSubstitutionDao.java │ │ │ ├── data │ │ │ ├── CardIDGenerator.java │ │ │ ├── CharNumberGenerator.java │ │ │ ├── NumberGenerator.java │ │ │ └── RandomGenerator.java │ │ │ ├── dataForger │ │ │ └── TestDataFactory.java │ │ │ ├── entity │ │ │ ├── InterfaceMsg.java │ │ │ ├── InterfaceMsg_.java │ │ │ ├── TestCase.java │ │ │ ├── TestCase_.java │ │ │ ├── TestStreamEntity.java │ │ │ ├── VariableSubstitution.java │ │ │ └── VariableSubstitution_.java │ │ │ ├── listener │ │ │ └── AssertListener.java │ │ │ ├── service │ │ │ ├── TestResultService.java │ │ │ └── impl │ │ │ │ ├── JpaWXCaseService.java │ │ │ │ └── TestResultServiceImpl.java │ │ │ ├── swagger2 │ │ │ ├── Swagger2Config.java │ │ │ └── example │ │ │ │ ├── ParaPost.java │ │ │ │ └── PostCase.java │ │ │ ├── testcase │ │ │ └── QYWXTestCase.java │ │ │ └── utils │ │ │ ├── AssertionOverrideUtil.java │ │ │ ├── Base64Util.java │ │ │ ├── BaseTestngInit.java │ │ │ ├── CreateIDCardNo.java │ │ │ ├── DateUtils.java │ │ │ ├── EasyPoiExcelStyleUtil.java │ │ │ ├── EasyPoiUtil.java │ │ │ ├── Json.java │ │ │ ├── JsonUtils.java │ │ │ ├── LoadStaticConfigUtil.java │ │ │ ├── Log4jUtil.java │ │ │ ├── RandomDataKit.java │ │ │ ├── RestTemplateUtils.java │ │ │ ├── SendEmail.java │ │ │ ├── SpringContextUtil.java │ │ │ └── VariableUtil.java │ └── org │ │ └── hibernate │ │ └── cfg │ │ └── PropertyContainer.java └── resources │ ├── MindUML.puml │ ├── application-dev.yml │ ├── application.yml │ ├── log4j2.xml │ ├── mock │ ├── have-paramaters-get.json │ ├── have-paramaters-post-json.json │ ├── have-paramaters-post.json │ ├── json-paramaters-havecookies-post-2.json │ ├── json-paramaters-havecookies-post.json │ ├── json-paramaters-haveheaders-post.json │ ├── no-paramaters-get-302.json │ ├── no-paramaters-get-responsehavecookies.json │ ├── no-paramaters-get1.json │ ├── no-paramaters-get2.json │ ├── no-paramaters-post.json │ ├── noparamaters-havecookies-get.json │ └── readme.md │ ├── static │ ├── css │ │ └── extent.css │ ├── index.html │ └── js │ │ └── extent.js │ ├── testcaseexcel │ └── 企业微信接口测试集.xls │ └── testng.xml └── test └── java └── testcase ├── Algorithm.java ├── ConcurrentTestCase.java ├── RandomParameter.java ├── SpringBootTestCase.java ├── StreamStudy.java ├── StreamStudyCase.java ├── SumJavaLine.java ├── Test.java └── TestCaseDemo.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=java 2 | *.css linguist-language=java 3 | *.html linguist-language=java 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | .idea 26 | *.iws 27 | *.iml 28 | *.ipr 29 | target/ 30 | testoutput/ 31 | test-output/ -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 基础镜像是docker仓库的java:8(JDK8) 2 | FROM java:8 3 | # 作者签名 4 | MAINTAINER czy czy725@yeat.com 5 | # 挂载宿主机jar包到镜像 /platform-pay-1.0.0.jar 和 下个指令对应即可,命名并非一定要和jar名一样,为了能够识别 6 | copy test-1.0-SNAPSHOT.jar /test-1.0-SNAPSHOT.jar 7 | # 执行 java -jar 命令,启动容器跟随启动 8 | CMD java -jar /test-1.0-SNAPSHOT.jar 9 | # 设置对外端口为 8090 10 | EXPOSE 8090 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # java-elf 项目实行接口关键字+数据驱动模式开发测试 2 | 3 | - 关键字 4 | 5 | 该项目可以通过”接口名称“关键字,匹配该接口名称下的测试用例。 6 | 7 | - 数据驱动数据驱动目前实行两种途径 8 | 9 | 1、excel数据驱动(比较传统) 10 | 示例代码见:EasypoiWxCaseService类 11 | 12 | 2、数据库数据驱动(更易用于扩展) 13 | 示例代码见:JpaWXCaseService类 14 | 15 | 可以根据自己维护用例的习惯进行其中的数据驱动选择 16 | 17 | 3、持续测试集成 18 | 配置jdk环境和maven环境并运行: 19 | ```$xslt 20 | mvn clean test 21 | ``` 22 | 执行testng.xml文件中配置的测试套件 23 | 24 | 4、本地maven编译推送至远程maven库 25 | ``` 26 | mvn clean deploy -X -Dmaven.test.skip=true 27 | 28 | ``` 29 | 30 | 4、~~功能废弃-新增测试用例动态生成(必填项为空,必填项缺省、超长长度...),实际测试中后端对于必填为空、超长长度、类型不一致等校验统一处理,验证一个即为其他为参数空情况的验证覆盖~~ 31 | ``` 32 | //简单示例 33 | //请求参数 34 | { 35 | "parames1": "11", 36 | "parames2": "22", 37 | "parames3": "33" 38 | } 39 | //返回结果 40 | { 41 | "参数值:parames1为空返回结果": { 42 | "parames1": "", 43 | "parames2": "22", 44 | "parames3": "33" 45 | }, 46 | "参数值:parames2为空返回结果": { 47 | "parames1": "11", 48 | "parames2": "", 49 | "parames3": "33" 50 | }, 51 | "参数值:parames3为空返回结果": { 52 | "parames1": "11", 53 | "parames2": "22", 54 | "parames3": "" 55 | } 56 | } 57 | 58 | ``` 59 | 5、跳出接口测试误区,接口更适合做冒烟和回归测试。虽然接口测试的本质也是功能测试,但接口的测试粒度应该是根据后端接收参数处理逻辑来定。 60 | 61 | 6、增加随机数据生成: 62 | ``` 63 | Random(String[0,10]) 64 | Random(Char[10]) 65 | Random(Long[10]) 66 | Random(Boolean) 67 | 入参数参数直接写随机函数即可,eg: 68 | { 69 | "data":{ 70 | "key1":"测试-numRandom(Long[2])", 71 | "key2":"测试-Random(Char[3])" 72 | } 73 | } 74 | //对应会生成:测试-num34的随机数和测试-jh的随机数 75 | ``` 76 | -------------------------------------------------------------------------------- /allure-results/04254a7b-6cfa-45dd-bcc8-b6e9fffc0575-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"04254a7b-6cfa-45dd-bcc8-b6e9fffc0575","name":"Default Suite","children":["1c8bd668-f52b-4b79-8444-48231ffef5d4"],"befores":[],"afters":[],"links":[],"start":1621758906533,"stop":1621758916718} -------------------------------------------------------------------------------- /allure-results/047586f6-20d3-40c5-bc19-a7c22396890f-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"047586f6-20d3-40c5-bc19-a7c22396890f","name":"Java-elf","children":["2a612220-49ef-4e1d-9bcc-2e9a2e4dd0b4"],"befores":[],"afters":[],"links":[],"start":1619145174213,"stop":1619145184358} -------------------------------------------------------------------------------- /allure-results/09d3a09f-7b79-4883-a688-d91189ec1500-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"09d3a09f-7b79-4883-a688-d91189ec1500","name":"Default Suite","children":["277427b6-6ec7-41f7-8ea4-4f49223d04bc"],"befores":[],"afters":[],"links":[],"start":1621759183869,"stop":1621759194026} -------------------------------------------------------------------------------- /allure-results/1c8bd668-f52b-4b79-8444-48231ffef5d4-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"1c8bd668-f52b-4b79-8444-48231ffef5d4","name":"Java-elf","children":["f723aea0-c711-4bf0-a2ea-8c868420050c"],"befores":[],"afters":[],"links":[],"start":1621758906535,"stop":1621758916707} -------------------------------------------------------------------------------- /allure-results/24a8d093-bf10-4512-8c3c-be02defe92f0-result.json: -------------------------------------------------------------------------------- 1 | {"name":"getTestRandom","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1619176776083,"stop":1619176776093,"uuid":"24a8d093-bf10-4512-8c3c-be02defe92f0","historyId":"9eb6e359eda1074ca0eb1ef24bf157fa","fullName":"testcase.TestCaseDemo.getTestRandom","labels":[{"name":"package","value":"testcase.TestCaseDemo"},{"name":"testClass","value":"testcase.TestCaseDemo"},{"name":"testMethod","value":"getTestRandom"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.TestCaseDemo"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"63540@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /allure-results/277427b6-6ec7-41f7-8ea4-4f49223d04bc-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"277427b6-6ec7-41f7-8ea4-4f49223d04bc","name":"Java-elf","children":["295a76f3-cf06-4cd8-b05b-6099cc3a5c2b"],"befores":[],"afters":[],"links":[],"start":1621759183872,"stop":1621759194020} -------------------------------------------------------------------------------- /allure-results/28f33310-3b0c-4d92-a709-89c3c18c482c-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"28f33310-3b0c-4d92-a709-89c3c18c482c","name":"Default Suite","children":["349b293e-e3f7-4ecb-9c1c-5ca9329776b2"],"befores":[],"afters":[],"links":[],"start":1619181164525,"stop":1619181174684} -------------------------------------------------------------------------------- /allure-results/295a76f3-cf06-4cd8-b05b-6099cc3a5c2b-result.json: -------------------------------------------------------------------------------- 1 | {"name":"lambadTest","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1621759193956,"stop":1621759193962,"uuid":"295a76f3-cf06-4cd8-b05b-6099cc3a5c2b","historyId":"d40d21be4620023b993d5e7d8844dce3","fullName":"testcase.StreamStudyCase.lambadTest","labels":[{"name":"package","value":"testcase.StreamStudyCase"},{"name":"testClass","value":"testcase.StreamStudyCase"},{"name":"testMethod","value":"lambadTest"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.StreamStudyCase"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"992@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /allure-results/2a612220-49ef-4e1d-9bcc-2e9a2e4dd0b4-result.json: -------------------------------------------------------------------------------- 1 | {"name":"getTestRandom","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1619145184295,"stop":1619145184305,"uuid":"2a612220-49ef-4e1d-9bcc-2e9a2e4dd0b4","historyId":"9eb6e359eda1074ca0eb1ef24bf157fa","fullName":"testcase.TestCaseDemo.getTestRandom","labels":[{"name":"package","value":"testcase.TestCaseDemo"},{"name":"testClass","value":"testcase.TestCaseDemo"},{"name":"testMethod","value":"getTestRandom"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.TestCaseDemo"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"8949@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /allure-results/2e4aa861-8a82-4687-8e98-8634967b3445-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"2e4aa861-8a82-4687-8e98-8634967b3445","name":"Default Suite","children":["a1e93c62-ede2-445b-bd5a-1c1eae4f9ffd"],"befores":[],"afters":[],"links":[],"start":1621759490392,"stop":1621759500543} -------------------------------------------------------------------------------- /allure-results/349b293e-e3f7-4ecb-9c1c-5ca9329776b2-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"349b293e-e3f7-4ecb-9c1c-5ca9329776b2","name":"Java-elf","children":["8aacbeb5-5ba6-4aca-946c-f7ade72411d6"],"befores":[],"afters":[],"links":[],"start":1619181164528,"stop":1619181174677} -------------------------------------------------------------------------------- /allure-results/4718a26e-2d86-495f-8566-7269e150b666-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"4718a26e-2d86-495f-8566-7269e150b666","name":"testcase.StreamStudyCase","children":["295a76f3-cf06-4cd8-b05b-6099cc3a5c2b"],"befores":[],"afters":[],"links":[],"start":1621759183876,"stop":1621759194024} -------------------------------------------------------------------------------- /allure-results/4a8a4f53-5975-4c41-bb0b-f56209d8a85d-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"4a8a4f53-5975-4c41-bb0b-f56209d8a85d","name":"Java-elf","children":["24a8d093-bf10-4512-8c3c-be02defe92f0"],"befores":[],"afters":[],"links":[],"start":1619176765990,"stop":1619176776158} -------------------------------------------------------------------------------- /allure-results/57fe5ed7-b155-4762-907a-b931eed869a7-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"57fe5ed7-b155-4762-907a-b931eed869a7","name":"Default Suite","children":["4a8a4f53-5975-4c41-bb0b-f56209d8a85d"],"befores":[],"afters":[],"links":[],"start":1619176765986,"stop":1619176776165} -------------------------------------------------------------------------------- /allure-results/7271ebb1-f987-409e-91ea-2bc4f275cc12-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"7271ebb1-f987-409e-91ea-2bc4f275cc12","name":"testcase.TestCaseDemo","children":["24a8d093-bf10-4512-8c3c-be02defe92f0"],"befores":[],"afters":[],"links":[],"start":1619176765995,"stop":1619176776164} -------------------------------------------------------------------------------- /allure-results/77d30321-4250-4ace-b403-01504dcfc6d2-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"77d30321-4250-4ace-b403-01504dcfc6d2","name":"testcase.StreamStudyCase","children":["f907ec45-a992-46d3-a226-9b3920083580"],"befores":[],"afters":[],"links":[],"start":1621759490398,"stop":1621759500542} -------------------------------------------------------------------------------- /allure-results/8aacbeb5-5ba6-4aca-946c-f7ade72411d6-result.json: -------------------------------------------------------------------------------- 1 | {"name":"getTestRandom","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1619181174601,"stop":1619181174615,"uuid":"8aacbeb5-5ba6-4aca-946c-f7ade72411d6","historyId":"9eb6e359eda1074ca0eb1ef24bf157fa","fullName":"testcase.TestCaseDemo.getTestRandom","labels":[{"name":"package","value":"testcase.TestCaseDemo"},{"name":"testClass","value":"testcase.TestCaseDemo"},{"name":"testMethod","value":"getTestRandom"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.TestCaseDemo"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"73994@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /allure-results/9632b653-fbeb-4baa-a6ac-ceb73b13008c-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"9632b653-fbeb-4baa-a6ac-ceb73b13008c","name":"testcase.TestCaseDemo","children":["8aacbeb5-5ba6-4aca-946c-f7ade72411d6"],"befores":[],"afters":[],"links":[],"start":1619181164532,"stop":1619181174683} -------------------------------------------------------------------------------- /allure-results/a1e93c62-ede2-445b-bd5a-1c1eae4f9ffd-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"a1e93c62-ede2-445b-bd5a-1c1eae4f9ffd","name":"Java-elf","children":["f907ec45-a992-46d3-a226-9b3920083580"],"befores":[],"afters":[],"links":[],"start":1621759490394,"stop":1621759500537} -------------------------------------------------------------------------------- /allure-results/ca0d5021-bc46-4670-a63d-5790bf49cd50-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"ca0d5021-bc46-4670-a63d-5790bf49cd50","name":"Default Suite","children":["047586f6-20d3-40c5-bc19-a7c22396890f"],"befores":[],"afters":[],"links":[],"start":1619145174210,"stop":1619145184370} -------------------------------------------------------------------------------- /allure-results/ce62675b-5caf-4262-b409-ea3bbfe266d8-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"ce62675b-5caf-4262-b409-ea3bbfe266d8","name":"testcase.TestCaseDemo","children":["2a612220-49ef-4e1d-9bcc-2e9a2e4dd0b4"],"befores":[],"afters":[],"links":[],"start":1619145174218,"stop":1619145184368} -------------------------------------------------------------------------------- /allure-results/e9977e95-297b-499c-aa8d-87d0e7c00602-container.json: -------------------------------------------------------------------------------- 1 | {"uuid":"e9977e95-297b-499c-aa8d-87d0e7c00602","name":"testcase.StreamStudyCase","children":["f723aea0-c711-4bf0-a2ea-8c868420050c"],"befores":[],"afters":[],"links":[],"start":1621758906540,"stop":1621758916716} -------------------------------------------------------------------------------- /allure-results/f723aea0-c711-4bf0-a2ea-8c868420050c-result.json: -------------------------------------------------------------------------------- 1 | {"name":"lambadTest","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1621758916632,"stop":1621758916640,"uuid":"f723aea0-c711-4bf0-a2ea-8c868420050c","historyId":"d40d21be4620023b993d5e7d8844dce3","fullName":"testcase.StreamStudyCase.lambadTest","labels":[{"name":"package","value":"testcase.StreamStudyCase"},{"name":"testClass","value":"testcase.StreamStudyCase"},{"name":"testMethod","value":"lambadTest"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.StreamStudyCase"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"938@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /allure-results/f907ec45-a992-46d3-a226-9b3920083580-result.json: -------------------------------------------------------------------------------- 1 | {"name":"lambdaList","status":"passed","statusDetails":{"known":false,"muted":false,"flaky":false},"stage":"finished","steps":[],"attachments":[],"parameters":[],"start":1621759500476,"stop":1621759500482,"uuid":"f907ec45-a992-46d3-a226-9b3920083580","historyId":"995edcd3cefeac8983983e671a202b0","fullName":"testcase.StreamStudyCase.lambdaList","labels":[{"name":"package","value":"testcase.StreamStudyCase"},{"name":"testClass","value":"testcase.StreamStudyCase"},{"name":"testMethod","value":"lambdaList"},{"name":"parentSuite","value":"Default Suite"},{"name":"suite","value":"Java-elf"},{"name":"subSuite","value":"testcase.StreamStudyCase"},{"name":"host","value":"cuizhongyuandeMacBook-Pro.local"},{"name":"thread","value":"1064@cuizhongyuandeMacBook-Pro.local.main(1)"},{"name":"framework","value":"testng"},{"name":"language","value":"java"}],"links":[]} -------------------------------------------------------------------------------- /database/javaelf_init.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : 192.168.1.225 5 | Source Server Type : MySQL 6 | Source Server Version : 50723 7 | Source Host : 192.168.1.225:3306 8 | Source Schema : javaelf 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 50723 12 | File Encoding : 65001 13 | 14 | Date: 05/11/2020 14:12:00 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for interface_msg 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `interface_msg`; 24 | CREATE TABLE `interface_msg` ( 25 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 26 | `request_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 27 | `url_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 28 | PRIMARY KEY (`id`) USING BTREE 29 | ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 30 | 31 | -- ---------------------------- 32 | -- Records of interface_msg 33 | -- ---------------------------- 34 | INSERT INTO `interface_msg` VALUES (1, 'post', 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'); 35 | INSERT INTO `interface_msg` VALUES (2, 'post', 'http://127.0.0.1:8091'); 36 | 37 | -- ---------------------------- 38 | -- Table structure for test_case 39 | -- ---------------------------- 40 | DROP TABLE IF EXISTS `test_case`; 41 | CREATE TABLE `test_case` ( 42 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 43 | `case_status` int(11) NULL DEFAULT NULL, 44 | `interfacemsg_id` bigint(20) NULL DEFAULT NULL, 45 | `desc_case` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 46 | `headers_parames` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 47 | `body_parames` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 48 | `expect` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 49 | `actual` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, 50 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 51 | PRIMARY KEY (`id`) USING BTREE 52 | ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 53 | 54 | -- ---------------------------- 55 | -- Records of test_case 56 | -- ---------------------------- 57 | INSERT INTO `test_case` VALUES (1, 1, 1, 'corpid/corpsecret参数均为空', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"\",\"corpsecret\":\"\"}', '\" \"\"errcode\"\": 41004,', NULL, NULL); 58 | INSERT INTO `test_case` VALUES (2, 1, 1, 'corpid传、corpsecret为空', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"${corpidTrue}\",\"corpsecret\":\"\"}', ' \"\"errmsg\"\": \"\"corpsecret missing\"\"\"', NULL, NULL); 59 | INSERT INTO `test_case` VALUES (3, 1, 1, 'corpid为空、corpsecret传', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"\",\"corpsecret\":\"${corpsecretTrue}\"}', '\" \"\"errcode\"\": 41004,', NULL, NULL); 60 | INSERT INTO `test_case` VALUES (4, 1, 1, 'corpid正确传、corpsecret错误传', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"${corpidTrue}\",\"corpsecret\":\"${corpidFalse}\"}', ' \"\"errmsg\"\": \"\"corpsecret missing\"\"', NULL, NULL); 61 | INSERT INTO `test_case` VALUES (5, 1, 1, 'corpid错误传、corpsecret正确传', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"${corpidFalse}\",\"corpsecret\":\"${corpsecretTrue}\"}', '}\"', NULL, NULL); 62 | INSERT INTO `test_case` VALUES (6, 1, 1, 'corpid、corpsecret均错误传', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"${corpidFalse}\",\"corpsecret\":\"${corpidFalse}\"}', '\" \"\"errcode\"\": 41002,', NULL, NULL); 63 | INSERT INTO `test_case` VALUES (7, 1, 1, 'corpid、corpsecret均正确传', '{\"Content-Type\":\"application/json\"}', '{\"corpid\":\"${corpidTrue}\",\"corpsecret\":\"${corpsecretTrue}\"}', ' \"\"errmsg\"\": \"\"corpid missing\"\"\"', NULL, NULL); 64 | 65 | -- ---------------------------- 66 | -- Table structure for variable_substitution 67 | -- ---------------------------- 68 | DROP TABLE IF EXISTS `variable_substitution`; 69 | CREATE TABLE `variable_substitution` ( 70 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 71 | `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 72 | `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 73 | `reflect_calss` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 74 | `reflect_method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 75 | `reflect_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 76 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, 77 | PRIMARY KEY (`id`) USING BTREE 78 | ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 79 | 80 | -- ---------------------------- 81 | -- Records of variable_substitution 82 | -- ---------------------------- 83 | INSERT INTO `variable_substitution` VALUES (1, '${corpidTrue}', '', 'com.javaelf.dataForger.TestDataFactory', 'getCorpidTrue', 'ww27d6f876d80ceec6', '有效corpid'); 84 | INSERT INTO `variable_substitution` VALUES (2, '${corpidFalse}', '', 'com.javaelf.dataForger.TestDataFactory', 'getCorpidFalse', 'ww27d6f876d80ceec', '无效corpid'); 85 | INSERT INTO `variable_substitution` VALUES (3, '${corpsecretTrue}', '', 'com.javaelf.dataForger.TestDataFactory', 'getCorpsecretTrue', 'elaiRGcWe4JLESzypgnabA3Tvpj8kLiV6zLEqa4Nbw8', '有效corpsecret'); 86 | INSERT INTO `variable_substitution` VALUES (4, '${corpsecretFalse}', '', 'com.javaelf.dataForger.TestDataFactory', 'getCorpsecretFalse', 'elaiRGcWe4JLESzypgnabA3Tvpj8kLiV6zLEqa4Nbw', '无效corpsecret'); 87 | 88 | SET FOREIGN_KEY_CHECKS = 1; 89 | -------------------------------------------------------------------------------- /docker-auto.sh: -------------------------------------------------------------------------------- 1 | echo "老铁我们开始吧!!!" 2 | #操作/项目路径(Dockerfile存放的路径) 3 | BASE_PATH=/work/dockerimage 4 | # 源jar路径 5 | SOURCE_PATH=/work/dockerimage/target 6 | # 项目运行jar路径 7 | PROJECT_PATH=/work/dockerimage/project 8 | # 项目备份jar路径 9 | BACKUP_PATH=/work/dockerimage/backup 10 | #docker 镜像/容器名字或者jar名字 这里都命名为这个 11 | CONTAINER_NAME=test 12 | SERVER_NAME=test-1.0-SNAPSHOT 13 | #端口映射 14 | MAIN_PORT=8090 15 | SERVER_PORT=8090 16 | #容器id 17 | CID=$(docker ps -a | grep "$CONTAINER_NAME" | awk '{print $1}') 18 | #镜像id 19 | IID=$(docker images | grep "$SERVER_NAME" | awk '{print $3}') 20 | DATE=`date +%Y%m%d%H%M` 21 | # 最新构建代码移动到项目环境 22 | function transfer(){ 23 | echo "新构建代码$SOURCE_PATH/$SERVER_NAME.jar 移至$PROJECT_PATH ...." 24 | cp $SOURCE_PATH/$SERVER_NAME.jar $PROJECT_PATH 25 | cp $SOURCE_PATH/Dockerfile $PROJECT_PATH 26 | echo "迁移完成" 27 | } 28 | # 备份 29 | function backup(){ 30 | if [ -f "$SOURCE_PATH/$SERVER_NAME.jar" ]; then 31 | echo "$SERVER_NAME.jar 备份..." 32 | cp $SOURCE_PATH/$SERVER_NAME.jar $BACKUP_PATH/$SERVER_NAME-$DATE.jar 33 | echo "备份 $SERVER_NAME.jar 完成" 34 | else 35 | echo "$SOURCE_PATH/$SERVER_NAME.jar不存在,跳过备份" 36 | fi 37 | } 38 | # 构建docker镜像 39 | function build(){ 40 | if [ -n "$IID" ]; then 41 | echo "存在$SERVER_NAME镜像,IID=$IID,开始删除镜像并重新构建镜像$SERVER_NAME" 42 | docker rmi -f $SERVER_NAME 43 | else 44 | echo "不存在$SERVER_NAME镜像,开始构建镜像" 45 | 46 | fi 47 | #构建 48 | cd $PROJECT_PATH 49 | docker build --no-cache=true -t $SERVER_NAME . 50 | } 51 | 52 | 53 | 54 | GIT_USERNAME=15238305317 55 | GIT_PWD=czy 56 | GIT_PROJECT_PATH=/work/dockerimage/workspace/open-platform 57 | 58 | # 运行docker容器 59 | function run(){ 60 | 61 | #自动更新git项目 expect插件安装 yum -y install expect 62 | echo "============拉取代码===========" 63 | cd $GIT_PROJECT_PATH 64 | expect -c "spawn git pull origin; expect \"*Username*\" { send \"${GIT_USERNAME}\n\"; exp_continue } \"*Password*\" { send \"${GIT_PWD}\n\" }; interact" 65 | 66 | echo "============打包tools===========" 67 | cd $GIT_PROJECT_PATH/platform-tools/ 68 | mvn install 69 | 70 | echo "============打包id-server===========" 71 | cd $GIT_PROJECT_PATH/platform-id-server/ 72 | mvn install 73 | 74 | echo "============打包entity-server===========" 75 | cd $GIT_PROJECT_PATH/platform-entity-server/ 76 | mvn install 77 | 78 | echo "============打包pay===========" 79 | cd $GIT_PROJECT_PATH/platform-pay/ 80 | mvn install 81 | 82 | echo "============复制pay===========" 83 | cp -rf target/$SERVER_NAME.jar $SOURCE_PATH 84 | 85 | 86 | 87 | 88 | 89 | #备份镜像 90 | backup 91 | #迁移(代码构建产物到运行环境) 92 | transfer 93 | #构建镜像 94 | build 95 | #删除历史缓存镜像 96 | #echo "删除历史缓存镜像" 97 | #docker images|grep none|awk '{print $3 }'|xargs docker rmi 98 | 99 | if [ -n "$CID" ]; then 100 | echo "存在$CONTAINER_NAME容器,CID=$CID,停止docker:$CONTAINER_NAME容器 ..." 101 | docker stop $CONTAINER_NAME 102 | echo "删除$CONTAINER_NAME容器" 103 | docker rm $CONTAINER_NAME 104 | echo "$CONTAINER_NAME容器清除完成" 105 | else 106 | echo "不存在$CONTAINER_NAME容器,无须清理容器..." 107 | # docker run --name $CONTAINER_NAME -v $BASE_PATH:$BASE_PATH -d -p $MAIN_PORT:$SERVER_PORT $SERVER_NAME 108 | # echo "$SERVER_NAME容器创建完成" 109 | fi 110 | 111 | echo "开始创建镜像$SERVER_NAME的容器$CONTAINER_NAME,端口映射$MAIN_PORT>>>$SERVER_PORT" 112 | docker run --name $CONTAINER_NAME -v $BASE_PATH:$BASE_PATH -d -p $MAIN_PORT:$SERVER_PORT --net=host $SERVER_NAME 113 | echo "$CONTAINER_NAME容器创建结束" 114 | docker ps 115 | #输出10分钟内的启动日志 116 | docker logs --since 10m $CONTAINER_NAME 117 | } 118 | #入口 119 | run 120 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | interface-test 8 | java-elf 9 | 1.0-SNAPSHOT 10 | java-elf接口自动化项目 11 | jar 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 2.2.9.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-logging 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-log4j2 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-autoconfigure 50 | 51 | 52 | 53 | org.projectlombok 54 | lombok 55 | 1.18.4 56 | 57 | 58 | 59 | org.testng 60 | testng 61 | 6.14.3 62 | 63 | 64 | 65 | cn.afterturn 66 | easypoi-spring-boot-starter 67 | 4.2.0 68 | 69 | 70 | io.qameta.allure 71 | allure-testng 72 | 2.10.0 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | commons-io 83 | commons-io 84 | 2.4 85 | 86 | 87 | cn.hutool 88 | hutool-all 89 | 5.3.5 90 | 91 | 92 | org.apache.commons 93 | commons-lang3 94 | 95 | 96 | com.google.code.gson 97 | gson 98 | 2.8.5 99 | 100 | 101 | 102 | mysql 103 | mysql-connector-java 104 | 8.0.19 105 | 106 | 107 | org.hibernate 108 | hibernate-core 109 | 5.4.15.Final 110 | 111 | 112 | org.hibernate 113 | hibernate-entitymanager 114 | 5.4.15.Final 115 | 116 | 117 | com.alibaba 118 | druid-spring-boot-starter 119 | 1.1.22 120 | 121 | 122 | org.springframework.data 123 | spring-data-jpa 124 | 2.2.0.M4 125 | 126 | 127 | org.springframework 128 | spring-test 129 | 5.2.8.RELEASE 130 | 131 | 132 | org.springframework.boot 133 | spring-boot-test 134 | 135 | 136 | 137 | com.github.javafaker 138 | javafaker 139 | 1.0.2 140 | 141 | 142 | org.apache.httpcomponents 143 | httpclient 144 | 4.5.8 145 | 146 | 147 | log4j 148 | log4j 149 | 1.2.12 150 | 151 | 152 | 153 | javax.mail 154 | mail 155 | 1.4 156 | 157 | 158 | 159 | io.springfox 160 | springfox-swagger-ui 161 | 2.9.2 162 | 163 | 164 | io.springfox 165 | springfox-swagger2 166 | 2.9.2 167 | 168 | 169 | commons-lang 170 | commons-lang 171 | 2.6 172 | 173 | 174 | 175 | com.github.mifmif 176 | generex 177 | 1.0.2 178 | 179 | 180 | 181 | 182 | 183 | org.springframework.boot 184 | spring-boot-maven-plugin 185 | 186 | 187 | org.apache.maven.plugins 188 | maven-surefire-plugin 189 | 2.22.2 190 | 191 | 192 | src/main/resources/testng.xml 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/JavaElfApplication.java: -------------------------------------------------------------------------------- 1 | package com.javaelf; 2 | 3 | import com.javaelf.utils.SpringContextUtil; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.ApplicationContext; 9 | 10 | /** 11 | * @author czy-2020727 12 | */ 13 | @EnableConfigurationProperties 14 | @SpringBootApplication(exclude = MongoAutoConfiguration.class) 15 | public class JavaElfApplication { 16 | public static void main(String[] args) { 17 | ApplicationContext context = SpringApplication.run(com.javaelf.JavaElfApplication.class, args); 18 | SpringContextUtil.setApplicationContext(context); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/base/TestBase.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.base; 2 | 3 | 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; 7 | import org.testng.annotations.AfterClass; 8 | import org.testng.annotations.BeforeClass; 9 | 10 | @Component 11 | @SpringBootTest 12 | public class TestBase extends AbstractTestNGSpringContextTests { 13 | /** 14 | * base测试类 15 | */ 16 | /** 17 | * BeforeClass 18 | */ 19 | @BeforeClass(alwaysRun = true) 20 | public void beforeClass() { 21 | //todo 需要执行前的操作 22 | } 23 | /** 24 | * AfterClass 25 | */ 26 | @AfterClass(alwaysRun = true) 27 | public void afterClass() { 28 | //todo 执行用例后回写 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/controller/TestResultsController.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.controller; 2 | 3 | import com.javaelf.service.TestResultService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.*; 6 | 7 | import java.util.*; 8 | 9 | 10 | /** 11 | * 测试后实际结果查询 12 | * 13 | **/ 14 | @RestController 15 | @RequestMapping("/api") 16 | public class TestResultsController { 17 | 18 | @Autowired 19 | TestResultService testResultService; 20 | 21 | /** 22 | * 获取实际测试的结果--json格式 23 | * 24 | **/ 25 | @PostMapping(value = "/test/actual") 26 | public List getACtual(){ 27 | return testResultService.getActualTestResult(); 28 | } 29 | /** 30 | * 区分必填项和非必填项 31 | * 通过组合算法动态生成参数某一必填项未传的异常测试用例 32 | * 33 | **/ 34 | @PostMapping(value = "/test/mandatoryParams") 35 | public String MandatoryTest(@RequestBody String reqJson){ 36 | return testResultService.mandatory(reqJson); 37 | } 38 | /** 39 | * 不区分参数的必填项和非必须 40 | * 通过组合算法动态生成参数某一填项未传的测试用例组 41 | * 42 | **/ 43 | @PostMapping(value = "/test/hybridParams") 44 | public String Mandatory(@RequestBody String reqJson){ 45 | return testResultService.hybrid(reqJson); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/dao/InterfaceMsgDao.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.dao; 2 | 3 | import com.javaelf.entity.InterfaceMsg; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface InterfaceMsgDao extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/dao/TestCaseDao.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.dao; 2 | 3 | import com.javaelf.entity.TestCase; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.transaction.Transactional; 11 | import java.util.List; 12 | 13 | 14 | @Repository 15 | public interface TestCaseDao extends JpaRepository { 16 | @Transactional 17 | @Modifying 18 | @Query( "UPDATE TestCase SET actual = :actual WHERE id = :id" ) 19 | void updateActual(@Param( "actual" ) String actual, @Param( "id" ) Long id); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/dao/VariableSubstitutionDao.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.dao; 2 | 3 | import com.javaelf.entity.VariableSubstitution; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.transaction.Transactional; 11 | 12 | @Repository 13 | public interface VariableSubstitutionDao extends JpaRepository { 14 | @Transactional 15 | @Modifying 16 | @Query( "UPDATE VariableSubstitution SET reflectValue = :reflectValue WHERE name = :variableName" ) 17 | void updateVariableValue(@Param( "reflectValue" ) String reflectValue, @Param( "variableName" ) String variableName); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/data/NumberGenerator.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.data; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.ThreadLocalRandom; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * 随机数生成器 10 | * 11 | * @author niaoshuai 12 | * @author shixing 13 | */ 14 | public class NumberGenerator { 15 | 16 | private static final String NUMBER_CHAR = "0123456789"; 17 | 18 | /** 19 | * 生成随机数 20 | * @param length 21 | * @return 22 | */ 23 | public static int randomInt(Integer length) { 24 | Random rm = new Random(); 25 | if (length == 0 ){ 26 | return 0; 27 | }else { 28 | int i = rm.nextInt(length); 29 | return i; 30 | } 31 | } 32 | 33 | /** 34 | * 获取指定范围随机数 35 | * @param startIndex 36 | * @param endIndex 37 | * @return 38 | */ 39 | public static int randomInt(int startIndex,int endIndex ) { 40 | Random rm = new Random(); 41 | int i = rm.nextInt(endIndex+1-startIndex)+startIndex; 42 | return i; 43 | } 44 | 45 | 46 | /** 47 | * @Author zgq 48 | * @Description 生成有序的编号 0000 前缀长度 49 | * @Date 20-9-24 下午4:49 50 | * @param endIndex 51 | * @return java.lang.String 52 | **/ 53 | public static String orderInt(int endIndex) { 54 | String result=""; 55 | for (int i = 1; i <= endIndex; i++) { 56 | if (i < 10) { 57 | result = "000" + i; 58 | System.out.println(result); 59 | } else if (i >= 100) { 60 | result = "000" + i; 61 | System.out.println(result); 62 | } else if (i >= 1000) { 63 | result = "000" + i; 64 | System.out.println(result); 65 | } else if (i >= 10000) { 66 | // result = String(int); 67 | System.out.println(i); 68 | } else 69 | { System.out.println("0000" + i); 70 | } 71 | } 72 | return result ; 73 | } 74 | 75 | /** 76 | * @Author zgq 77 | * @Description 生成规则设备编号:设备类型+五位编号(从1开始,不够前补0) 78 | * @Date 20-9-24 下午5:24 79 | * @param equipmentType 80 | * @param equipmentNo 81 | * @return java.lang.String 82 | **/ 83 | public static String getNewEquipmentNo(String equipmentType, String equipmentNo){ 84 | String newEquipmentNo = ""; 85 | 86 | if(equipmentNo != null && !equipmentNo.isEmpty()){ 87 | int newEquipment = Integer.parseInt(equipmentNo) + 1; 88 | newEquipmentNo = String.format(equipmentType + "%05d", newEquipment); 89 | } 90 | return newEquipmentNo; 91 | } 92 | 93 | 94 | 95 | public static String generateStringByLength(int length) { 96 | StringBuffer sb = new StringBuffer(); 97 | Random random = new Random(); 98 | for (int i = 0; i < length; i++) { 99 | sb.append(NUMBER_CHAR.charAt(random.nextInt(NUMBER_CHAR.length()))); 100 | } 101 | return sb.toString(); 102 | } 103 | 104 | public static final char[] CHARR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~!@#$%^&*.?-+=_".toCharArray(); 105 | public static final String PASSWORD_REGEX = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]{8,16}$"; 106 | public static final String NO_CHINESE_REGEX = "^[^\\u4e00-\\u9fa5]+$"; 107 | public static final Pattern PASSWORD_PATTERN = Pattern.compile(PASSWORD_REGEX); 108 | public static final Pattern NO_CHINESE_PATTERN = Pattern.compile(NO_CHINESE_REGEX); 109 | /** 110 | * 生成密码 111 | * @param length 112 | * @return 113 | */ 114 | public static String generatePassword(int length) { 115 | length = length < 6 ? 6 : length; 116 | length = length > 16 ? 16 : length; 117 | String result = getRandomPassword(length); 118 | Matcher m = PASSWORD_PATTERN.matcher(result); 119 | Matcher m1 = NO_CHINESE_PATTERN.matcher(result); 120 | if (m.matches() && m1.matches()) { 121 | return result; 122 | } 123 | return generatePassword(length); 124 | } 125 | 126 | public static String getRandomPassword(int length) { 127 | StringBuilder sb = new StringBuilder(); 128 | ThreadLocalRandom r = ThreadLocalRandom.current(); 129 | for (int i = 0; i < length; i++) { 130 | sb.append(CHARR[r.nextInt(CHARR.length)]); 131 | } 132 | return sb.toString(); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/data/RandomGenerator.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.data; 2 | 3 | import java.util.Random; 4 | 5 | public class RandomGenerator { 6 | 7 | public static boolean getRandomBoolean() { 8 | Random random = new Random(); 9 | return random.nextBoolean(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/dataForger/TestDataFactory.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.dataForger; 2 | 3 | import com.github.javafaker.Faker; 4 | import org.springframework.stereotype.Component; 5 | import org.testng.annotations.Test; 6 | 7 | import java.util.Locale; 8 | 9 | 10 | /** 11 | * 数据工厂伪造者,可以提供测试数据工厂数据:常用的姓名、电话号码、地址、随机数等 12 | */ 13 | @Component 14 | public class TestDataFactory { 15 | 16 | /** 17 | * 企业微信测试数据工厂 18 | */ 19 | //企业ID-正确 20 | public String getCorpidTrue(){ 21 | String corpid = "ww27d6f876d80ceec6"; 22 | return corpid; 23 | } 24 | 25 | //应用的凭证密钥-正确 26 | public String getCorpsecretTrue(){ 27 | String corpsecret = "elaiRGcWe4JLESzypgnabA3Tvpj8kLiV6zLEqa4Nbw8"; 28 | return corpsecret; 29 | } 30 | //企业ID-错误 31 | public String getCorpidFalse(){ 32 | String corpid = "ww27d6f876d80ceec"; 33 | return corpid; 34 | } 35 | 36 | //应用的凭证密钥-错误 37 | public String getCorpsecretFalse(){ 38 | String corpsecret = "elaiRGcWe4JLESzypgnabA3Tvpj8kLiV6zLEqa4Nbw"; 39 | return corpsecret; 40 | } 41 | /*** 42 | * 初始Faker对象,并使用CHINA信息 43 | */ 44 | Faker faker = new Faker(new Locale("zh-CN")); 45 | public String getName(){ 46 | String name = faker.phoneNumber().cellPhone(); 47 | return name; 48 | } 49 | @Test 50 | public void tt(){ 51 | 52 | System.out.println(getName()); 53 | } 54 | 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/InterfaceMsg.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import cn.afterturn.easypoi.excel.annotation.Excel; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import org.hibernate.annotations.DynamicInsert; 8 | import org.hibernate.annotations.DynamicUpdate; 9 | 10 | import javax.persistence.*; 11 | import javax.validation.constraints.NotBlank; 12 | 13 | /** 14 | * 15 | *URL访问路径 --PO(Persistent Object):持久化对象 16 | * 17 | *@author CZY 18 | *@date 2020-5-31 13:43:37 19 | **/ 20 | @Setter 21 | @Getter 22 | @Entity 23 | @Table(name = "interfaceMsg") 24 | @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"}) 25 | @DynamicInsert 26 | @DynamicUpdate 27 | public class InterfaceMsg { 28 | private static final long serialVersionUID = 1L; 29 | /** 30 | * url的id 31 | */ 32 | @GeneratedValue(strategy= GenerationType.IDENTITY) 33 | @NotBlank(message = "id不能为空") 34 | @Id 35 | private Long id; 36 | /** 37 | * 请求类型:get/post/put/delete/update 38 | */ 39 | @NotBlank(message = "请求类型不能为空") 40 | private String requestType ; 41 | /** 42 | * 请求地址address 43 | */ 44 | @NotBlank(message = "url地址不能为空") 45 | private String urlAddress; 46 | /** 47 | * 请求参数 48 | */ 49 | private String params; 50 | /** 51 | * 备注信息 52 | */ 53 | private String remark; 54 | 55 | } -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/InterfaceMsg_.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | import javax.persistence.metamodel.StaticMetamodel; 5 | 6 | /** 7 | *被测url信息 --实体类校验 8 | * 9 | *@author czy 10 | *@date 2020-5-31 13:43:37 11 | **/ 12 | @StaticMetamodel(InterfaceMsg.class) 13 | public class InterfaceMsg_ { 14 | public static volatile SingularAttribute id; 15 | public static volatile SingularAttribute requestType; 16 | public static volatile SingularAttribute urlAddress; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/TestCase.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.annotations.DynamicInsert; 7 | import org.hibernate.annotations.DynamicUpdate; 8 | 9 | import javax.persistence.*; 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * 14 | *测试用例 --PO(Persistent Object):持久化对象 15 | * 16 | *@author CZY 17 | *@date 2020-5-31 13:43:37 18 | **/ 19 | @Setter 20 | @Getter 21 | @Entity 22 | @Table(name = "testCase") 23 | @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"}) 24 | @DynamicInsert 25 | @DynamicUpdate 26 | public class TestCase { 27 | private static final long serialVersionUID = 1L; 28 | /** 29 | * url的id 30 | */ 31 | @GeneratedValue(strategy= GenerationType.IDENTITY) 32 | @NotBlank(message = "id不能为空") 33 | @Id 34 | private Long id; 35 | /** 36 | * 绑定状态 0 正向测试 1 反向测试 37 | */ 38 | private Integer caseStatus; 39 | /** 40 | * 接口信息对应的id 41 | */ 42 | private Long interfacemsgId ; 43 | /** 44 | * 用例描述 45 | */ 46 | private String descCase; 47 | /** 48 | * 请求头参数 49 | */ 50 | private String headersParames; 51 | /** 52 | * 请求体参数 53 | */ 54 | private String bodyParames; 55 | /** 56 | * 期望结果 57 | */ 58 | private String expect; 59 | /** 60 | * 实际响应结果 61 | */ 62 | private String actual; 63 | /** 64 | * 备注信息 65 | */ 66 | private String remark; 67 | 68 | } -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/TestCase_.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | 4 | import javax.persistence.metamodel.SingularAttribute; 5 | import javax.persistence.metamodel.StaticMetamodel; 6 | 7 | /** 8 | *被测url信息 --实体类校验 9 | * 10 | *@author czy 11 | *@date 2020-5-31 13:43:37 12 | **/ 13 | @StaticMetamodel(TestCase.class) 14 | public class TestCase_ { 15 | public static volatile SingularAttribute id; 16 | public static volatile SingularAttribute caseStatus; 17 | public static volatile SingularAttribute interfacemsgId; 18 | public static volatile SingularAttribute headersParames; 19 | public static volatile SingularAttribute bodyParames; 20 | public static volatile SingularAttribute expect; 21 | public static volatile SingularAttribute actual; 22 | public static volatile SingularAttribute remark; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/TestStreamEntity.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * stream流的测试类-学习stream流使用,不做其他用途 10 | * */ 11 | @Getter 12 | @Setter 13 | @AllArgsConstructor 14 | @ToString 15 | public class TestStreamEntity { 16 | /** 17 | * 姓名 18 | * */ 19 | public String name; 20 | /** 21 | * 性别 22 | * */ 23 | public String sex; 24 | /** 25 | * 年龄 26 | * */ 27 | public int age; 28 | /** 29 | * 年级 30 | * */ 31 | public int grade; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/VariableSubstitution.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.annotations.DynamicInsert; 7 | import org.hibernate.annotations.DynamicUpdate; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.persistence.*; 11 | import javax.validation.constraints.NotBlank; 12 | 13 | @Setter 14 | @Getter 15 | @Entity 16 | @Table(name = "variableSubstitution") 17 | @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"}) 18 | @DynamicInsert 19 | @DynamicUpdate 20 | public class VariableSubstitution { 21 | private static final long serialVersionUID = 1L; 22 | /** 23 | * url的id 24 | */ 25 | @GeneratedValue(strategy= GenerationType.IDENTITY) 26 | @NotBlank(message = "id不能为空") 27 | @Id 28 | private Long id; 29 | /** 30 | * 变量名 31 | */ 32 | @NotBlank(message = "变量名不能为空") 33 | @Length(max = 32,message = "最大32位") 34 | @Column(nullable = false,length = 32) 35 | private String name; 36 | /** 37 | * 变量值 38 | */ 39 | private String value; 40 | /** 41 | * 反射的类名 42 | */ 43 | private String reflectCalss; 44 | /** 45 | * 反射类的方法 46 | */ 47 | private String reflectMethod; 48 | /** 49 | * 反射方法返回的值 50 | */ 51 | private String reflectValue; 52 | /** 53 | * 备注信息 54 | */ 55 | private String remark; 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/entity/VariableSubstitution_.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.entity; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | import javax.persistence.metamodel.StaticMetamodel; 5 | 6 | @StaticMetamodel( VariableSubstitution.class) 7 | public class VariableSubstitution_ { 8 | public static volatile SingularAttribute id; 9 | public static volatile SingularAttribute name; 10 | public static volatile SingularAttribute value; 11 | public static volatile SingularAttribute reflectCalss; 12 | public static volatile SingularAttribute reflectMethod; 13 | public static volatile SingularAttribute reflectValue; 14 | public static volatile SingularAttribute remark; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/listener/AssertListener.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.listener; 2 | 3 | import com.javaelf.utils.AssertionOverrideUtil; 4 | import org.testng.ITestResult; 5 | import org.testng.TestListenerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 集成allure报告 12 | * 13 | * @author czy 14 | * @date 2020/7/15 15 | */ 16 | public class AssertListener extends TestListenerAdapter { 17 | 18 | @Override 19 | public void onTestStart(ITestResult result) { 20 | AssertionOverrideUtil.flag = true; 21 | AssertionOverrideUtil.errors.clear(); 22 | } 23 | 24 | @Override 25 | public void onTestFailure(ITestResult tr) { 26 | this.handleAssertion(tr); 27 | } 28 | 29 | @Override 30 | public void onTestSkipped(ITestResult tr) { 31 | this.handleAssertion(tr); 32 | } 33 | 34 | @Override 35 | public void onTestSuccess(ITestResult tr) { 36 | this.handleAssertion(tr); 37 | } 38 | 39 | private int index = 0; 40 | 41 | private void handleAssertion(ITestResult tr){ 42 | if(!AssertionOverrideUtil.flag){ 43 | Throwable throwable = tr.getThrowable(); 44 | if(throwable==null){ 45 | throwable = new Throwable(); 46 | } 47 | StackTraceElement[] traces = throwable.getStackTrace(); 48 | StackTraceElement[] alltrace = new StackTraceElement[0]; 49 | for (Error e : AssertionOverrideUtil.errors) { 50 | StackTraceElement[] errorTraces = e.getStackTrace(); 51 | StackTraceElement[] et = this.getKeyStackTrace(tr, errorTraces); 52 | StackTraceElement[] message = new StackTraceElement[]{new StackTraceElement("message : "+e.getMessage()+" in method : ", tr.getMethod().getMethodName(), tr.getTestClass().getRealClass().getSimpleName(), index)}; 53 | index = 0; 54 | alltrace = this.merge(alltrace, message); 55 | alltrace = this.merge(alltrace, et); 56 | } 57 | if(traces!=null){ 58 | traces = this.getKeyStackTrace(tr, traces); 59 | alltrace = this.merge(alltrace, traces); 60 | } 61 | throwable.setStackTrace(alltrace); 62 | tr.setThrowable(throwable); 63 | AssertionOverrideUtil.flag = true; 64 | AssertionOverrideUtil.errors.clear(); 65 | tr.setStatus(ITestResult.FAILURE); 66 | } 67 | } 68 | 69 | private StackTraceElement[] getKeyStackTrace(ITestResult tr, StackTraceElement[] stackTraceElements){ 70 | List ets = new ArrayList(); 71 | for (StackTraceElement stackTraceElement : stackTraceElements) { 72 | if(stackTraceElement.getClassName().equals(tr.getTestClass().getName())){ 73 | ets.add(stackTraceElement); 74 | index = stackTraceElement.getLineNumber(); 75 | } 76 | } 77 | StackTraceElement[] et = new StackTraceElement[ets.size()]; 78 | for (int i = 0; i < et.length; i++) { 79 | et[i] = ets.get(i); 80 | } 81 | return et; 82 | } 83 | 84 | private StackTraceElement[] merge(StackTraceElement[] traces1, StackTraceElement[] traces2){ 85 | StackTraceElement[] ste = new StackTraceElement[traces1.length+traces2.length]; 86 | for (int i = 0; i < traces1.length; i++) { 87 | ste[i] = traces1[i]; 88 | } 89 | for (int i = 0; i < traces2.length; i++) { 90 | ste[traces1.length+i] = traces2[i]; 91 | } 92 | return ste; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/service/TestResultService.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.service; 2 | 3 | 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | @Service 9 | public interface TestResultService { 10 | /** 11 | * 获取实际测试结果 12 | * 13 | * @return 14 | */ 15 | List getActualTestResult(); 16 | /** 17 | * 动态生成必填项未传异常测试用例集 18 | * 19 | * @return 20 | */ 21 | String mandatory(String reqJson); 22 | /** 23 | * 动态生成混合参数的测试用例集 24 | * 25 | * @return 26 | */ 27 | String hybrid(String reqJson); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/service/impl/JpaWXCaseService.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.service.impl; 2 | 3 | import com.javaelf.dao.InterfaceMsgDao; 4 | import com.javaelf.dao.TestCaseDao; 5 | import com.javaelf.dao.VariableSubstitutionDao; 6 | import com.javaelf.entity.InterfaceMsg; 7 | import com.javaelf.entity.TestCase; 8 | import com.javaelf.entity.VariableSubstitution; 9 | import com.javaelf.utils.AssertionOverrideUtil; 10 | import com.javaelf.utils.JsonUtils; 11 | import com.javaelf.utils.RestTemplateUtils; 12 | import com.javaelf.utils.VariableUtil; 13 | import io.qameta.allure.Allure; 14 | import io.qameta.allure.model.Status; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.*; 19 | 20 | @Component 21 | public class JpaWXCaseService { 22 | @Autowired 23 | private InterfaceMsgDao interfaceMsgDao; 24 | @Autowired 25 | private TestCaseDao testCaseDao; 26 | @Autowired 27 | private VariableSubstitutionDao variableSubstitutionDao; 28 | 29 | public void getToken() { 30 | List interfaceMsgList = interfaceMsgDao.findAll(); 31 | List testCaseList = testCaseDao.findAll(); 32 | List variableSubstitutionList = variableSubstitutionDao.findAll(); 33 | List responseList = new ArrayList<>(); 34 | for (InterfaceMsg interfaceMsg : interfaceMsgList) { 35 | if (interfaceMsg.getId() != null) { 36 | for (TestCase testCase : testCaseList) { 37 | String parames = testCase.getBodyParames(); 38 | if (testCase.getInterfacemsgId().equals(interfaceMsg.getId())) { 39 | if (testCase.getInterfacemsgId().equals(interfaceMsg.getId())) { 40 | //调用工具类把body的变量名替换为变量值并写入数据库中 41 | parames = VariableUtil.replaceVariables(parames, variableSubstitutionList,variableSubstitutionDao); 42 | //请求参数写入到allure报告中 43 | Allure.addAttachment("Request", parames); 44 | Map paramesVariableValueMap = JsonUtils.json2map(parames); 45 | //get请求拼接 46 | String url = interfaceMsg.getUrlAddress(); 47 | url = url + "?corpid=" + paramesVariableValueMap.get("corpid") + "&corpsecret=" + paramesVariableValueMap.get("corpsecret"); 48 | String response = RestTemplateUtils.get(url, String.class).getBody(); 49 | System.out.println(response); 50 | //预期结果断言 51 | Map assertExpectMap = JsonUtils.json2map(response); 52 | int expected = (int) assertExpectMap.get("errcode"); 53 | if (expected == 0) { 54 | Allure.step("测试通过!---这是预期的成功", Status.PASSED); 55 | //响应结果写入allure报告中 56 | Allure.addAttachment("Response", response); 57 | } else { 58 | Allure.step("测试通过!---这是预期的失败", Status.FAILED); 59 | //响应结果写入allure报告中 60 | Allure.addAttachment("Response", response); 61 | } 62 | AssertionOverrideUtil.verifyEquals(expected, 0); 63 | //区分测试类型0是正向,1是反向 64 | if (testCase.getCaseStatus()==0){ 65 | response = "正向测试响应结果----- : "+response; 66 | }else { 67 | response = "反向测试响应结果----- : "+ response; 68 | } 69 | //获取响应结果更新数据库 70 | testCaseDao.updateActual(response, testCase.getId()); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/service/impl/TestResultServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.service.impl; 2 | 3 | import com.javaelf.dao.TestCaseDao; 4 | import com.javaelf.entity.TestCase; 5 | import com.javaelf.service.TestResultService; 6 | import com.javaelf.utils.JsonUtils; 7 | import org.apache.commons.lang.StringEscapeUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.testng.annotations.Test; 11 | 12 | 13 | import java.util.*; 14 | import java.util.stream.Collectors; 15 | 16 | @Service 17 | public class TestResultServiceImpl implements TestResultService { 18 | 19 | @Autowired 20 | TestCaseDao testCaseDao; 21 | 22 | /** 23 | * 查询实际执行测试用例的结果 24 | * 25 | * */ 26 | @Override 27 | public List getActualTestResult() { 28 | List testCases = testCaseDao.findAll(); 29 | List getActual = new ArrayList<>(); 30 | for (TestCase testCase : testCases){ 31 | getActual.add(testCase.getActual()); 32 | } 33 | return getActual; 34 | } 35 | /** 36 | * 必填项未传的用例组合---根据参数必填项某一个未传+非必传参数,组合生成新的请求参数用例 37 | * 38 | * 39 | * @return*/ 40 | public String mandatory(String reqJson) { 41 | Map map = JsonUtils.json2map(reqJson); 42 | Map yesMap = (Map) map.get("yes"); 43 | Map noMap = (Map) map.get("no"); 44 | Set set = yesMap.keySet(); 45 | List> list = (List>) set.stream().map(m -> { 46 | Map hashMap = new HashMap<>(); 47 | //获取需要组合的必填项参数 48 | hashMap.put(m.toString(), yesMap.get(m)); 49 | return hashMap; 50 | }).collect(Collectors.toList()); 51 | Map objectMap = new HashMap<>(); 52 | for (int i = 0; i < list.size(); i++) { 53 | StringBuilder stringBuilder = new StringBuilder(); 54 | int finalI = i; 55 | list.stream().peek(mapParam -> { 56 | if (!list.get(finalI).equals(mapParam)) { 57 | stringBuilder.append(JsonUtils.mapToJson(mapParam)); 58 | } 59 | }).collect(Collectors.toList()); 60 | stringBuilder.append(JsonUtils.mapToJson(noMap)); 61 | objectMap.put("必填项" + list.get(i) + "为空的请求参数: ", stringBuilder.toString().replace("}{", ",")); 62 | } 63 | String str = JsonUtils.mapToJson(objectMap); 64 | str = StringEscapeUtils.unescapeJava(str); 65 | str=str.replace(" \":\"{"," \":{"); 66 | str=str.replace("}\",\"","},\""); 67 | str=str.replace("}\"}","}}"); 68 | System.out.println(str); 69 | return str; 70 | } 71 | 72 | /** 73 | * 根据参数数生成某一个参数缺省测试用例集 74 | * 75 | * 76 | * @return*/ 77 | @Override 78 | public String hybrid(String reqJson) { 79 | Map map = JsonUtils.json2map(reqJson); 80 | TreeMap treeMap = new TreeMap(map); 81 | Set set = treeMap.keySet(); 82 | TreeMap treeMap1 = new TreeMap(); 83 | set.forEach(key ->{ 84 | Map reqMap = new HashMap(); 85 | treeMap.forEach((k,v)->{ 86 | if (key.equals(k)){ 87 | reqMap.put(k.toString(),""); 88 | }else { 89 | reqMap.put(k.toString(),v.toString()); 90 | } 91 | }); 92 | String format = String.format("参数值:%s为空返回结果", key); 93 | treeMap1.put(format,reqMap); 94 | }); 95 | 96 | return JsonUtils.mapToJson(treeMap1); 97 | } 98 | 99 | /** 100 | * 异常测试--必填项缺省 101 | *接受正确参数--返回某个必填项参数缺省的入参参数 102 | * 默认取第一个参数为必填项,使用时需注意 103 | * @reqJson 104 | * */ 105 | public String getMissParams(String reqJson){ 106 | Map reqMap = JsonUtils.json2map(reqJson); 107 | Set set = reqMap.keySet(); 108 | List> list = (List>) set.stream().map(m ->{ 109 | Map respMap = new HashMap(); 110 | respMap.put(m.toString(),reqMap.get(m)); 111 | return respMap; 112 | }).collect(Collectors.toList()); 113 | list.remove(0); 114 | String respStr = JsonUtils.obj2json(list); 115 | if (respStr.contains("},{")){ 116 | respStr = respStr.replace("},{",","); 117 | } 118 | return respStr; 119 | } 120 | /** 121 | * 异常测试--必填项为"" 122 | *接受正确参数--返回某个必填项参数值为:”“ 123 | * 默认取第一个参数为必填项,使用时需注意 124 | * @reqJson 125 | * */ 126 | public String getParamsNull(String reqJson){ 127 | Map reqMap = JsonUtils.json2map(reqJson); 128 | Set set = reqMap.keySet(); 129 | List> list = (List>) set.stream().map(m ->{ 130 | Map respMap = new HashMap(); 131 | respMap.put(m.toString(),reqMap.get(m)); 132 | return respMap; 133 | }).collect(Collectors.toList()); 134 | Map replaceMap = list.get(0); 135 | Set set1 = replaceMap.keySet(); 136 | set1.forEach(key ->{ 137 | replaceMap.put(key,""); 138 | }); 139 | String respStr = JsonUtils.obj2json(list); 140 | if (respStr.contains("},{")){ 141 | respStr = respStr.replace("},{",","); 142 | } 143 | return respStr; 144 | } 145 | /** 146 | * 异常测试--必填项参数值长度超长测试 147 | *接受正确参数--返回某个必填项参数值超过设置长度 148 | * 默认取第一个参数为必填项,使用时需注意 149 | * @reqJson 150 | * */ 151 | public String getTooLong(String reqJson){ 152 | Map reqMap = JsonUtils.json2map(reqJson); 153 | Set set = reqMap.keySet(); 154 | List> list = (List>) set.stream().map(m ->{ 155 | Map respMap = new HashMap(); 156 | respMap.put(m.toString(),reqMap.get(m)); 157 | return respMap; 158 | }).collect(Collectors.toList()); 159 | Map replaceMap = list.get(0); 160 | Set set1 = replaceMap.keySet(); 161 | set1.forEach(key ->{ 162 | //由于参数值长度不固定,暂时不动态获取赋值,目前写死长度为256,有点low了,^ -^ 数据库varchar类型默认是255 163 | replaceMap.put(key,"TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" + 164 | "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" + 165 | "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" + 166 | "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" + 167 | "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT" + 168 | "TTTTTT"); 169 | }); 170 | String respStr = JsonUtils.obj2json(list); 171 | if (respStr.contains("},{")){ 172 | respStr = respStr.replace("},{",","); 173 | } 174 | return respStr; 175 | } 176 | /** 177 | * 异常测试--必填项参数类型不一致 178 | *接受正确参数--返回某个必填项参数类型不一致 179 | * 默认取第一个参数为必填项,使用时需注意 180 | * @reqJson 181 | * */ 182 | public String getTypeError(String reqJson){ 183 | Map reqMap = JsonUtils.json2map(reqJson); 184 | Set set = reqMap.keySet(); 185 | List> list = (List>) set.stream().map(m ->{ 186 | Map respMap = new HashMap(); 187 | respMap.put(m.toString(),reqMap.get(m)); 188 | return respMap; 189 | }).collect(Collectors.toList()); 190 | Map replaceMap = list.get(0); 191 | Set set1 = replaceMap.keySet(); 192 | set1.forEach(key ->{ 193 | //获取value类型 194 | if ( replaceMap.get(key) instanceof String){ 195 | //Integer.parseInt()就是把String类型转化为int类型 196 | replaceMap.put(key,Integer.parseInt((String) replaceMap.get(key))); 197 | }else if (replaceMap.get(key) instanceof Integer){ 198 | replaceMap.put(key,replaceMap.get(key).toString()); 199 | } 200 | }); 201 | String respStr = JsonUtils.obj2json(list); 202 | if (respStr.contains("},{")){ 203 | respStr = respStr.replace("},{",","); 204 | } 205 | return respStr; 206 | 207 | } 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/swagger2/Swagger2Config.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.swagger2; 2 | 3 | import com.google.common.base.Predicates; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import springfox.documentation.builders.ApiInfoBuilder; 7 | import springfox.documentation.builders.ParameterBuilder; 8 | import springfox.documentation.builders.PathSelectors; 9 | import springfox.documentation.builders.RequestHandlerSelectors; 10 | import springfox.documentation.schema.ModelRef; 11 | import springfox.documentation.service.ApiInfo; 12 | import springfox.documentation.service.Contact; 13 | import springfox.documentation.service.Parameter; 14 | import springfox.documentation.spi.DocumentationType; 15 | import springfox.documentation.spring.web.plugins.Docket; 16 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /*** 22 | * @ClassName: swagger2注册类 23 | * @Description: swagger2配置文件 24 | * @Auther: czy 25 | * @Date: 15:03 2020/05/09 26 | * @version : V0.1.0 27 | * swagger2 登录地址:http://ip:port/swagger-ui.html 28 | */ 29 | @Configuration 30 | @EnableSwagger2 31 | public class Swagger2Config { 32 | 33 | @Bean 34 | public Docket createRestApi() { 35 | //添加head参数配置start 36 | ParameterBuilder tokenPar = new ParameterBuilder(); 37 | List pars = new ArrayList<>(); 38 | tokenPar.name("header").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); 39 | pars.add(tokenPar.build()); 40 | //添加head参数配置end 41 | return new Docket(DocumentationType.SWAGGER_2) 42 | .apiInfo(apiInfo()) 43 | .select() 44 | // .apis(RequestHandlerSelectors.basePackage("com.interfaceproject.hibernate")) 45 | // 扫描多个controller包 46 | .apis( 47 | Predicates.or( 48 | RequestHandlerSelectors.basePackage("com.interfaceproject.developer.hibernatecase.controller"), 49 | RequestHandlerSelectors.basePackage("com.interfaceproject.developer.controller") 50 | )) 51 | 52 | .paths(PathSelectors.any()) 53 | .build() 54 | .globalOperationParameters(pars);//注意这里 55 | } 56 | 57 | //构建 api文档的详细信息函数 58 | private ApiInfo apiInfo() { 59 | return new ApiInfoBuilder() 60 | //页面标题 61 | .title("长沙超脑项目---- 接口测试用例管理----构建RESTful API") 62 | //创建人 63 | .contact(new Contact("博客地址", "https://www.jianshu.com/u/acf637a73f52", "")) 64 | //版本号 65 | .version("1.0") 66 | //描述 67 | .description("API 描述") 68 | .build(); 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/main/java/com/javaelf/swagger2/example/ParaPost.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.swagger2.example; 2 | 3 | import io.swagger.annotations.Api; 4 | import io.swagger.annotations.ApiOperation; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | // post请求上一个参数传入下一个请求示例 15 | @RestController 16 | @Api(value = "api",tags = "接口之间的相互调用--测试用例") 17 | public class ParaPost { 18 | 19 | @Autowired 20 | private PostCase postCase; 21 | 22 | @ApiOperation("case3--case2接口调用case1的接口") 23 | @PostMapping("/parapost") 24 | public Map postCase3(HttpServletRequest request, @RequestBody Map reqMap) throws Exception { 25 | try { 26 | Map resMap = postCase.postCase1(reqMap); 27 | String data = (String) resMap.get("data"); 28 | Map headerReqMap2 = new HashMap<>(); 29 | headerReqMap2.put("data", data); 30 | headerReqMap2.put("age", reqMap.get("age")); 31 | return postCase.postCase2(request, headerReqMap2); 32 | } catch (Exception e) { 33 | throw new Exception("请求失败"); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/swagger2/example/PostCase.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.swagger2.example; 2 | 3 | import com.javaelf.utils.CreateIDCardNo; 4 | import io.swagger.annotations.Api; 5 | import io.swagger.annotations.ApiOperation; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | 16 | /** 17 | *PostCase类供测试类方法调用 18 | *@author czy 19 | * @date 2020年05月09日 20 | */ 21 | 22 | @RestController 23 | @Api(value = "api",tags = "接口测试用例") 24 | public class PostCase { 25 | 26 | 27 | // 其中@PostMapping注解=@RequestMapping(value = "/postjson", method = RequestMethod.POST) 28 | // @RequestMapping(value = "/postjson", method = RequestMethod.POST) 29 | 30 | // post 请求无 header 参数的请求示例 31 | @ApiOperation(value ="case1--无header的post用例") 32 | @PostMapping("/jsonpost") 33 | public Map postCase1(@RequestBody Map reqMap) throws Exception { 34 | String name = (String) reqMap.get("name"); 35 | String age = (String) reqMap.get("age"); 36 | if ((null == name || "".equals(name)) || (null == age || "".equals(age))) { 37 | throw new Exception("参数异常"); 38 | } 39 | //这里用两种方式返回。1、Javabean对象 2、Map对象 40 | // User user = new User(12,"121","121","121"); 41 | // //这里需要把javabean对象转成字符串然后在转成map对象 42 | // return JsonUtils.json2map(JsonUtils.obj2json(user)); 43 | //Map对象返回响应 44 | Map resMap = new HashMap<>(); 45 | resMap.put("error", "1000"); 46 | resMap.put("mages", "success"); 47 | resMap.put("data","20200509"); 48 | return resMap; 49 | } 50 | // post请求带header参数的示例,header中包含:token ,jwt,session等 51 | @ApiOperation(value = "case2--有header的post用例") 52 | // @RequestMapping(value = "/headerpost",method = RequestMethod.POST) 53 | @PostMapping("/headerpost") 54 | public Map postCase2(HttpServletRequest request, @RequestBody Map reqMap) throws Exception { 55 | String data = (String)reqMap.get("data"); 56 | String age = (String) reqMap.get("age"); 57 | if ((null == data || "".equals(data)) || (null == age || "".equals(age))) { 58 | throw new Exception("参数异常"); 59 | } 60 | String token = request.getHeader("header"); 61 | System.out.println("token:"+token); 62 | String num = "123456789%"; 63 | 64 | //Map对象返回响应 65 | Map resMap = new HashMap<>(); 66 | resMap.put("address","北京六道口"); 67 | Map contMap = new HashMap<>(); 68 | contMap.put("error", "1000"); 69 | contMap.put("mages", "success"); 70 | contMap.put("data","20200509"); 71 | contMap.put("content",resMap); 72 | if( null == token || "".equals(token) || !token.equals(num)){ 73 | throw new Exception("token鉴权失败"); 74 | } 75 | return contMap; 76 | } 77 | @ApiOperation(value = "case3--身份证ID自动生成") 78 | @GetMapping("/getRandomID") 79 | public String getRandomID(){ 80 | String randomID = CreateIDCardNo.getRandomID(); 81 | return randomID; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/testcase/QYWXTestCase.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.testcase; 2 | 3 | import com.javaelf.base.TestBase; 4 | import com.javaelf.service.impl.JpaWXCaseService; 5 | import io.qameta.allure.Description; 6 | import io.qameta.allure.Severity; 7 | import io.qameta.allure.SeverityLevel; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.testng.annotations.Listeners; 10 | import org.testng.annotations.Test; 11 | 12 | @Listeners(com.javaelf.listener.AssertListener.class) 13 | public class QYWXTestCase extends TestBase { 14 | @Autowired 15 | JpaWXCaseService jpaWXCaseService; 16 | @Severity( SeverityLevel.BLOCKER) 17 | @Description("jpa示例--企业微信获取token覆盖测试") 18 | @Test 19 | public void gettokenJpaCase() { 20 | jpaWXCaseService.getToken(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/AssertionOverrideUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import org.testng.Assert; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 重写断言方法,捕获异常程序继续执行 10 | * 11 | * @author czy 12 | * @date 2020/7/15 13 | */ 14 | public class AssertionOverrideUtil { 15 | 16 | public static boolean flag = true; 17 | 18 | public static List errors = new ArrayList(); 19 | 20 | public static void verifyEquals(Object actual, Object expected){ 21 | try{ 22 | Assert.assertEquals(actual, expected); 23 | }catch(Error e){ 24 | errors.add(e); 25 | flag = false; 26 | } 27 | } 28 | 29 | public static void verifyEquals(Object actual, Object expected, String message){ 30 | try{ 31 | Assert.assertEquals(actual, expected, message); 32 | }catch(Error e){ 33 | errors.add(e); 34 | flag = false; 35 | } 36 | } 37 | 38 | public static void verifyTrue(Boolean actual ){ 39 | try{ 40 | Assert.assertTrue(actual); 41 | }catch(Error e){ 42 | errors.add(e); 43 | flag = false; 44 | } 45 | } 46 | 47 | public static void verifyTrue(Boolean actual,String message ){ 48 | try{ 49 | Assert.assertTrue(actual,message); 50 | }catch(Error e){ 51 | errors.add(e); 52 | flag = false; 53 | } 54 | } 55 | 56 | public static void verifyFalse(Boolean actual ){ 57 | try{ 58 | Assert.assertFalse(actual); 59 | }catch(Error e){ 60 | errors.add(e); 61 | flag = false; 62 | } 63 | } 64 | 65 | public static void verifyFalse(Boolean actual ,String message ){ 66 | try{ 67 | Assert.assertFalse(actual,message ); 68 | }catch(Error e){ 69 | errors.add(e); 70 | flag = false; 71 | } 72 | } 73 | 74 | public static void verifyNotNull(Object actual ){ 75 | try{ 76 | Assert.assertNotNull(actual); 77 | }catch(Error e){ 78 | errors.add(e); 79 | flag = false; 80 | } 81 | } 82 | 83 | public static void verifyNotNull(Object actual ,String message){ 84 | try{ 85 | Assert.assertNotNull(actual,message); 86 | }catch(Error e){ 87 | errors.add(e); 88 | flag = false; 89 | } 90 | } 91 | 92 | public static void verifyNull(Object actual ){ 93 | try{ 94 | Assert.assertNull(actual); 95 | }catch(Error e){ 96 | errors.add(e); 97 | flag = false; 98 | } 99 | } 100 | 101 | public static void verifyNull(Object actual,String message ){ 102 | try{ 103 | Assert.assertNull(actual,message); 104 | }catch(Error e){ 105 | errors.add(e); 106 | flag = false; 107 | } 108 | } 109 | 110 | public static void verifyEquals(String actual,String expected ){ 111 | try{ 112 | Assert.assertEquals(actual,expected); 113 | }catch(Error e){ 114 | errors.add(e); 115 | flag = false; 116 | } 117 | } 118 | 119 | public static void verifyEquals(String actual,String expected,String message ){ 120 | try{ 121 | Assert.assertEquals(actual,expected,message); 122 | }catch(Error e){ 123 | errors.add(e); 124 | flag = false; 125 | } 126 | } 127 | 128 | public static void verifyEquals(int actual,int expected ){ 129 | try{ 130 | Assert.assertEquals(actual,expected); 131 | }catch(Error e){ 132 | errors.add(e); 133 | flag = false; 134 | } 135 | } 136 | 137 | public static void verifyEquals(int actual,int expected,String message ){ 138 | try{ 139 | Assert.assertEquals(actual,expected,message); 140 | }catch(Error e){ 141 | errors.add(e); 142 | flag = false; 143 | } 144 | } 145 | 146 | 147 | 148 | public static void verifyEquals(long actual,long expected ){ 149 | try{ 150 | Assert.assertEquals(actual,expected); 151 | }catch(Error e){ 152 | errors.add(e); 153 | flag = false; 154 | } 155 | } 156 | 157 | public static void verifyEquals(long actual,long expected,String message ){ 158 | try{ 159 | Assert.assertEquals(actual,expected,message); 160 | }catch(Error e){ 161 | errors.add(e); 162 | flag = false; 163 | } 164 | } 165 | 166 | public static void verifyEquals(boolean actual,boolean expected ){ 167 | try{ 168 | Assert.assertEquals(actual,expected); 169 | }catch(Error e){ 170 | errors.add(e); 171 | flag = false; 172 | } 173 | } 174 | 175 | public static void verifyEquals(boolean actual,boolean expected ,String message){ 176 | try{ 177 | Assert.assertEquals(actual,expected,message); 178 | }catch(Error e){ 179 | errors.add(e); 180 | flag = false; 181 | } 182 | } 183 | 184 | public static void verifyEquals(short actual,short expected ){ 185 | try{ 186 | Assert.assertEquals(actual,expected); 187 | }catch(Error e){ 188 | errors.add(e); 189 | flag = false; 190 | } 191 | } 192 | 193 | public static void verifyEquals(short actual,short expected,String message ){ 194 | try{ 195 | Assert.assertEquals(actual,expected,message); 196 | }catch(Error e){ 197 | errors.add(e); 198 | flag = false; 199 | } 200 | } 201 | 202 | public static void verifyEquals(byte actual,byte expected ){ 203 | try{ 204 | Assert.assertEquals(actual,expected); 205 | }catch(Error e){ 206 | errors.add(e); 207 | flag = false; 208 | } 209 | } 210 | 211 | public static void verifyEquals(byte actual,byte expected ,String message){ 212 | try{ 213 | Assert.assertEquals(actual,expected,message); 214 | }catch(Error e){ 215 | errors.add(e); 216 | flag = false; 217 | } 218 | } 219 | 220 | public static void verifyEquals(char actual,char expected ){ 221 | try{ 222 | Assert.assertEquals(actual,expected); 223 | }catch(Error e){ 224 | errors.add(e); 225 | flag = false; 226 | } 227 | } 228 | 229 | public static void verifyEquals(char actual,char expected,String message ){ 230 | try{ 231 | Assert.assertEquals(actual,expected,message); 232 | }catch(Error e){ 233 | errors.add(e); 234 | flag = false; 235 | } 236 | } 237 | 238 | public static void verifyNotEquals(String actual,String expected ){ 239 | try{ 240 | Assert.assertNotEquals(actual,expected); 241 | }catch(Error e){ 242 | errors.add(e); 243 | flag = false; 244 | } 245 | } 246 | 247 | public static void verifyNotEquals(String actual,String expected,String message ){ 248 | try{ 249 | Assert.assertNotEquals(actual,expected,message); 250 | }catch(Error e){ 251 | errors.add(e); 252 | flag = false; 253 | } 254 | } 255 | 256 | public static void verifyfail(String message ){ 257 | try{ 258 | Assert.fail(message); 259 | }catch(Error e){ 260 | errors.add(e); 261 | flag = false; 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/Base64Util.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.FileOutputStream; 7 | import java.io.OutputStream; 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.Base64; 10 | 11 | /** 12 | * 此工具类的base64是基于JDK1.8实现的,jdk必须为1.8以上 13 | * 14 | * @author lgl 15 | */ 16 | public class Base64Util { 17 | public static final String UTF8 = "UTF-8"; 18 | public static final String GBK = "GBK"; 19 | private static Logger logger = LoggerFactory.getLogger(Base64Util.class); 20 | 21 | public Base64Util() { 22 | } 23 | 24 | public static String decodeBase64(String base64String) { 25 | return decodeBase64(base64String, UTF8); 26 | } 27 | 28 | public static String encodeBase64(String encodeData) { 29 | return encodeBase64(encodeData, UTF8); 30 | } 31 | 32 | /** 33 | * base64解密 34 | * 35 | * @param base64String 36 | * @param charset 37 | * @return 38 | */ 39 | public static String decodeBase64(String base64String, String charset) { 40 | try { 41 | return new String(Base64.getDecoder().decode(base64String), charset); 42 | } catch (UnsupportedEncodingException e) { 43 | e.printStackTrace(); 44 | if (logger.isDebugEnabled()) { 45 | logger.debug(e.getMessage()); 46 | } 47 | return null; 48 | } 49 | } 50 | 51 | /** 52 | * base64加密 53 | * 54 | * @param encodeData 55 | * @param charset 56 | * @return 57 | */ 58 | public static String encodeBase64(String encodeData, String charset) { 59 | try { 60 | return Base64.getEncoder().encodeToString(encodeData.getBytes(charset)); 61 | } catch (UnsupportedEncodingException e) { 62 | e.printStackTrace(); 63 | if (logger.isDebugEnabled()) { 64 | logger.debug(e.getMessage()); 65 | } 66 | return null; 67 | } 68 | } 69 | 70 | /** 71 | * base64字符串转换成图片 72 | * 73 | * @param imgStr base64字符串 74 | * @param imgFilePath 图片存放路径 75 | * @return 76 | * @author ZHANGJL 77 | * @dateTime 2018-02-23 14:42:17 78 | */ 79 | public static boolean base64ToImage(String imgStr, String imgFilePath, String imgName) { // 对字节数组字符串进行Base64解码并生成图片 80 | // 图像数据为空 81 | if (imgStr == null || "".equals(imgStr)) { 82 | return false; 83 | } 84 | try { 85 | // Base64解码 86 | byte[] b = Base64.getDecoder().decode(imgStr); 87 | for (int i = 0; i < b.length; ++i) { 88 | // 调整异常数据 89 | if (b[i] < 0) { 90 | b[i] += 256; 91 | } 92 | } 93 | OutputStream out = new FileOutputStream(imgFilePath + "/" + imgName + ".jpg"); 94 | out.write(b); 95 | out.flush(); 96 | out.close(); 97 | return true; 98 | } catch (Exception e) { 99 | return false; 100 | } 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/BaseTestngInit.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import com.beust.jcommander.Parameters; 4 | import org.testng.TestNG; 5 | import org.testng.xml.XmlClass; 6 | import org.testng.xml.XmlSuite; 7 | import org.testng.xml.XmlTest; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class BaseTestngInit { 12 | 13 | /** 14 | * 初始化testng 15 | */ 16 | public void baseTestngInitCode() { 17 | //创建testng对象 18 | TestNG testng = new TestNG(); 19 | //创建报告监听器对象 20 | // ExtentTestNGIReporterListener reportListener = new ExtentTestNGIReporterListener(); 21 | // TestLogListener testLogListener = new TestLogListener(); 22 | //设置需要执行的测试用例类 23 | testng.setTestClasses(new Class[] {}); 24 | //添加监听器 25 | // testng.addListener(reportListener); 26 | //运行测试 27 | testng.run(); 28 | } 29 | 30 | /** 31 | * 通过testng.xml初始化testng 32 | * @param xmlPath 33 | */ 34 | public void baseTestngInitXml(String xmlPath){ 35 | TestNG testNG = new TestNG(); 36 | List suites = new ArrayList(); 37 | suites.add(xmlPath); 38 | testNG.setTestSuites(suites); 39 | testNG.run(); 40 | } 41 | 42 | public void baseTestngInitVirtualXml(XmlSuite... suite){ 43 | List suites = new ArrayList<>(); 44 | for (XmlSuite i:suite) { 45 | suites.add(i); 46 | } 47 | TestNG tng = new TestNG(); 48 | tng.setXmlSuites(suites); 49 | tng.run(); 50 | 51 | } 52 | 53 | /* 54 | 55 | 56 | 57 | 58 | 59 | 60 | */ 61 | /** 62 | * 配置虚拟testng.xml 63 | */ 64 | public XmlSuite testngSuiteConfig(String suiteName,String testName,String... classPaths){ 65 | //创建suite节点 66 | XmlSuite suite = new XmlSuite(); 67 | //设置suite名称 68 | suite.setName(suiteName); 69 | //创建test节点 70 | XmlTest test = new XmlTest(suite); 71 | //设置节点名称 72 | test.setName(testName); 73 | //创建测试对象集合 74 | List classes = new ArrayList<>(); 75 | for (String classPath: classPaths) { 76 | classes.add(new XmlClass(classPath)); 77 | } 78 | test.setXmlClasses(classes) ; 79 | return suite; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/CreateIDCardNo.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | import java.util.Random; 7 | 8 | /** 9 | * 创建身份证号 10 | * 18位身份证号码各位的含义: 11 | * // 1-2位省、自治区、直辖市代码; 12 | * // 3-4位地级市、盟、自治州代码; 13 | * // 5-6位县、县级市、区代码; 14 | * // 7-14位出生年月日,比如19670401代表1967年4月1日; 15 | * // 15-17位为顺序号,其中17位(倒数第二位)男为单数,女为双数; 16 | * // 18位为校验码,0-9和X。 17 | * // 作为尾号的校验码,是由把前十七位数字带入统一的公式计算出来的, 18 | * // 计算的结果是0-10,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替, 19 | * // 因为如果用10做尾号,那么此人的身份证就变成了19位。X是罗马数字的10,用X来代替10 20 | * 21 | * @author kdc 22 | */ 23 | public class CreateIDCardNo { 24 | /** 25 | * 每位加权因子 26 | */ 27 | private static int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 28 | 8, 4, 2}; 29 | 30 | /** 31 | * 随机生成身份证号码 32 | * 33 | * @return 34 | */ 35 | public static String getRandomID() { 36 | String id = "420222199204179999"; 37 | // 随机生成省、自治区、直辖市代码 1-2 38 | String[] provinces = {"11", "12", "13", "14", "15", "21", "22", "23", 39 | "31", "32", "33", "34", "35", "36", "37", "41", "42", "43", 40 | "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", 41 | "63", "64", "65", "71", "81", "82"}; 42 | String province = randomOne(provinces); 43 | // 随机生成地级市、盟、自治州代码 3-4 44 | String city = randomCityCode(18); 45 | // 随机生成县、县级市、区代码 5-6 46 | String county = randomCityCode(28); 47 | // 随机生成出生年月 7-14 48 | String birth = randomBirth(20, 50); 49 | // 随机生成顺序号 15-17(随机性别) 50 | String no = new Random().nextInt(899) + 100 + ""; 51 | // // 随机生成校验码 18 52 | // String checks[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 53 | // "X" }; 54 | // String check = randomOne(checks); 55 | // 拼接身份证号码17位 56 | String id17 = province + city + county + birth + no; 57 | char[] c = id17.toCharArray(); 58 | int[] bit = converCharToInt(c); 59 | int sum17 = 0; 60 | sum17 = getPowerSum(bit); 61 | // 将和值与11取模得到余数进行校验码判断 62 | String checkCode = getCheckCodeBySum(sum17); 63 | id = id17 + checkCode; 64 | return id; 65 | } 66 | 67 | /** 68 | * 从String[] 数组中随机取出其中一个String字符串 69 | * 70 | * @param s 71 | * @return 72 | * @author mingzijian 73 | */ 74 | public static String randomOne(String[] s) { 75 | return s[new Random().nextInt(s.length - 1)]; 76 | } 77 | 78 | /** 79 | * 随机生成两位数的字符串(01-max),不足两位的前面补0 80 | * 81 | * @param max 82 | * @return 83 | * @author mingzijian 84 | */ 85 | public static String randomCityCode(int max) { 86 | int i = new Random().nextInt(max) + 1; 87 | return i > 9 ? i + "" : "0" + i; 88 | } 89 | 90 | /** 91 | * 随机生成minAge到maxAge年龄段的人的生日日期 92 | * 93 | * @param minAge 94 | * @param maxAge 95 | * @return 96 | * @author mingzijian 97 | */ 98 | public static String randomBirth(int minAge, int maxAge) { 99 | // 设置日期格式 100 | SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd"); 101 | Calendar date = Calendar.getInstance(); 102 | // 设置当前日期 103 | date.setTime(new Date()); 104 | // 随机设置日期为前maxAge年到前minAge年的任意一天 105 | int randomDay = 365 * minAge 106 | + new Random().nextInt(365 * (maxAge - minAge)); 107 | date.set(Calendar.DATE, date.get(Calendar.DATE) - randomDay); 108 | return dft.format(date.getTime()); 109 | } 110 | 111 | private static int[] converCharToInt(char[] c) throws NumberFormatException { 112 | int[] a = new int[c.length]; 113 | int k = 0; 114 | for (char temp : c) { 115 | a[k++] = Integer.parseInt(String.valueOf(temp)); 116 | } 117 | return a; 118 | } 119 | 120 | /** 121 | * 将身份证的每位和对应位的加权因子相乘之后,再得到和值 122 | * 123 | * @param bit 124 | * @return 125 | */ 126 | private static int getPowerSum(int[] bit) { 127 | int sum = 0; 128 | if (power.length != bit.length) { 129 | return sum; 130 | } 131 | for (int i = 0; i < bit.length; i++) { 132 | for (int j = 0; j < power.length; j++) { 133 | if (i == j) { 134 | sum = sum + bit[i] * power[j]; 135 | } 136 | } 137 | } 138 | return sum; 139 | } 140 | 141 | /** 142 | * 将和值与11取模得到余数进行校验码判断 143 | * 144 | * @param sum17 145 | * @return 校验位 146 | */ 147 | private static String getCheckCodeBySum(int sum17) { 148 | String checkCode = null; 149 | switch (sum17 % 11) { 150 | case 10: 151 | checkCode = "2"; 152 | break; 153 | case 9: 154 | checkCode = "3"; 155 | break; 156 | case 8: 157 | checkCode = "4"; 158 | break; 159 | case 7: 160 | checkCode = "5"; 161 | break; 162 | case 6: 163 | checkCode = "6"; 164 | break; 165 | case 5: 166 | checkCode = "7"; 167 | break; 168 | case 4: 169 | checkCode = "8"; 170 | break; 171 | case 3: 172 | checkCode = "9"; 173 | break; 174 | case 2: 175 | checkCode = "x"; 176 | break; 177 | case 1: 178 | checkCode = "0"; 179 | break; 180 | case 0: 181 | checkCode = "1"; 182 | break; 183 | default: 184 | checkCode = "1"; 185 | break; 186 | } 187 | return checkCode; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/EasyPoiExcelStyleUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | 4 | import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; 5 | import cn.afterturn.easypoi.excel.entity.params.ExcelForEachParams; 6 | import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler; 7 | import org.apache.poi.ss.usermodel.*; 8 | 9 | /** 10 | * @Description: 描述 11 | * @Author: lhc 12 | * @CreateDate: 2020/7/6 17:38 13 | */ 14 | public class EasyPoiExcelStyleUtil implements IExcelExportStyler { 15 | private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT"); 16 | private static final short FONT_SIZE_TEN = 10; 17 | private static final short FONT_SIZE_ELEVEN = 11; 18 | private static final short FONT_SIZE_TWELVE = 12; 19 | /** 20 | * 大标题样式 21 | */ 22 | private CellStyle headerStyle; 23 | /** 24 | * 每列标题样式 25 | */ 26 | private CellStyle titleStyle; 27 | /** 28 | * 数据行样式 29 | */ 30 | private CellStyle styles; 31 | 32 | public EasyPoiExcelStyleUtil(Workbook workbook) { 33 | this.init(workbook); 34 | } 35 | 36 | /** 37 | * 初始化样式 38 | * 39 | * @param workbook 40 | */ 41 | private void init(Workbook workbook) { 42 | this.headerStyle = initHeaderStyle(workbook); 43 | this.titleStyle = initTitleStyle(workbook); 44 | this.styles = initStyles(workbook); 45 | } 46 | 47 | /** 48 | * 大标题样式 49 | * 50 | * @param color 51 | * @return 52 | */ 53 | @Override 54 | public CellStyle getHeaderStyle(short color) { 55 | return headerStyle; 56 | } 57 | 58 | /** 59 | * 每列标题样式 60 | * 61 | * @param color 62 | * @return 63 | */ 64 | @Override 65 | public CellStyle getTitleStyle(short color) { 66 | return titleStyle; 67 | } 68 | 69 | /** 70 | * 数据行样式 71 | * 72 | * @param parity 可以用来表示奇偶行 73 | * @param entity 数据内容 74 | * @return 样式 75 | */ 76 | @Override 77 | public CellStyle getStyles(boolean parity, ExcelExportEntity entity) { 78 | return styles; 79 | } 80 | 81 | /** 82 | * 获取样式方法 83 | * 84 | * @param dataRow 数据行 85 | * @param obj 对象 86 | * @param data 数据 87 | */ 88 | @Override 89 | public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) { 90 | return getStyles(true, entity); 91 | } 92 | 93 | /** 94 | * 模板使用的样式设置 95 | */ 96 | @Override 97 | public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) { 98 | return null; 99 | } 100 | 101 | /** 102 | * 初始化--大标题样式 103 | * 104 | * @param workbook 105 | * @return 106 | */ 107 | private CellStyle initHeaderStyle(Workbook workbook) { 108 | CellStyle style = getBaseCellStyle(workbook); 109 | style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true)); 110 | return style; 111 | } 112 | 113 | /** 114 | * 初始化--每列标题样式 115 | * 116 | * @param workbook 117 | * @return 118 | */ 119 | private CellStyle initTitleStyle(Workbook workbook) { 120 | CellStyle style = getBaseCellStyle(workbook); 121 | style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false)); 122 | //背景色 123 | style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); 124 | style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 125 | return style; 126 | } 127 | 128 | /** 129 | * 初始化--数据行样式 130 | * 131 | * @param workbook 132 | * @return 133 | */ 134 | private CellStyle initStyles(Workbook workbook) { 135 | CellStyle style = getBaseCellStyle(workbook); 136 | style.setFont(getFont(workbook, FONT_SIZE_TEN, false)); 137 | style.setDataFormat(STRING_FORMAT); 138 | return style; 139 | } 140 | 141 | /** 142 | * 基础样式 143 | * 144 | * @return 145 | */ 146 | private CellStyle getBaseCellStyle(Workbook workbook) { 147 | CellStyle style = workbook.createCellStyle(); 148 | //下边框 149 | style.setBorderBottom(BorderStyle.THIN); 150 | //左边框 151 | style.setBorderLeft(BorderStyle.THIN); 152 | //上边框 153 | style.setBorderTop(BorderStyle.THIN); 154 | //右边框 155 | style.setBorderRight(BorderStyle.THIN); 156 | //水平居中 157 | style.setAlignment(HorizontalAlignment.CENTER); 158 | //上下居中 159 | style.setVerticalAlignment(VerticalAlignment.CENTER); 160 | //设置自动换行 161 | style.setWrapText(true); 162 | return style; 163 | } 164 | 165 | /** 166 | * 字体样式 167 | * 168 | * @param size 字体大小 169 | * @param isBold 是否加粗 170 | * @return 171 | */ 172 | private Font getFont(Workbook workbook, short size, boolean isBold) { 173 | Font font = workbook.createFont(); 174 | //字体样式 175 | font.setFontName("宋体"); 176 | //是否加粗 177 | font.setBold(isBold); 178 | //字体大小 179 | font.setFontHeightInPoints(size); 180 | return font; 181 | } 182 | } 183 | 184 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/EasyPoiUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | 4 | import cn.afterturn.easypoi.excel.ExcelExportUtil; 5 | import cn.afterturn.easypoi.excel.ExcelImportUtil; 6 | import cn.afterturn.easypoi.excel.entity.ExportParams; 7 | import cn.afterturn.easypoi.excel.entity.ImportParams; 8 | import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; 9 | import cn.afterturn.easypoi.excel.export.ExcelExportService; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 12 | import org.apache.poi.ss.usermodel.Workbook; 13 | import org.apache.poi.xssf.streaming.SXSSFWorkbook; 14 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 15 | import org.springframework.web.multipart.MultipartFile; 16 | 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.File; 19 | import java.io.FileOutputStream; 20 | import java.io.IOException; 21 | import java.net.URLEncoder; 22 | import java.util.*; 23 | 24 | import static cn.afterturn.easypoi.excel.ExcelExportUtil.USE_SXSSF_LIMIT; 25 | 26 | /** 27 | * @Description: Excel文件导入导出Util(EasyPoi) 28 | * @Author: lhc 29 | * @CreateDate: 2020/7/6 14:20 30 | */ 31 | public class EasyPoiUtil { 32 | /** 33 | * 功能描述:复杂导出Excel,包括文件名以及表名。创建表头 34 | * 35 | * @param list 导出的实体类 36 | * @param title 表头名称 37 | * @param sheetName sheet表名 38 | * @param pojoClass 映射的实体类 39 | * @param isCreateHeader 是否创建表头 40 | * @param fileName 41 | * @param response 42 | * @return 43 | */ 44 | public static void exportExcel(List list, String title, String sheetName, Class pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) { 45 | ExportParams exportParams = new ExportParams(title, sheetName); 46 | exportParams.setCreateHeadRows(isCreateHeader); 47 | exportParams.setStyle(EasyPoiExcelStyleUtil.class); 48 | defaultExport(list, pojoClass, fileName, response, exportParams); 49 | } 50 | 51 | public static void exportExcel(List list, String title, String sheetName, Class pojoClass, String fileName, boolean isCreateHeader) { 52 | ExportParams exportParams = new ExportParams(title, sheetName); 53 | exportParams.setCreateHeadRows(isCreateHeader); 54 | exportParams.setStyle(EasyPoiExcelStyleUtil.class); 55 | defaultExport(list, pojoClass, fileName, exportParams); 56 | } 57 | 58 | private static void defaultExport(List list, Class pojoClass, String fileName, ExportParams exportParams) { 59 | Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list); 60 | if (workbook != null) { 61 | downLoadExcel(fileName, workbook); 62 | } 63 | } 64 | /** 65 | * 功能描述:Excel导出 66 | * 67 | * @param fileName 文件名称 68 | * @param workbook Excel对象 69 | * @return 70 | */ 71 | public static void downLoadExcel(String fileName, Workbook workbook) { 72 | try { 73 | FileOutputStream fos = new FileOutputStream(fileName); 74 | workbook.write(fos); 75 | } catch (IOException e) { 76 | System.out.println("文件打开异常,请确认是否已打开"); 77 | } 78 | } 79 | /** 80 | * 功能描述:复杂导出Excel,包括文件名以及表名,不创建表头 81 | * 82 | * @param list 导出的实体类 83 | * @param title 表头名称 84 | * @param sheetName sheet表名 85 | * @param pojoClass 映射的实体类 86 | * @param fileName 87 | * @param response 88 | * @return 89 | */ 90 | public static void exportExcel(List list, String title, String sheetName, Class pojoClass, String fileName, HttpServletResponse response) { 91 | ExportParams exportParams = new ExportParams(title, sheetName); 92 | exportParams.setStyle(EasyPoiExcelStyleUtil.class); 93 | defaultExport(list, pojoClass, fileName, response, exportParams); 94 | } 95 | 96 | /** 97 | * 功能描述:Map 集合导出 98 | * 99 | * @param list 实体集合 100 | * @param fileName 导出的文件名称 101 | * @param response 102 | * @return 103 | */ 104 | public static void exportExcel(List> list, String fileName, HttpServletResponse response) { 105 | defaultExport(list, fileName, response); 106 | } 107 | 108 | /** 109 | * 功能描述:默认导出方法 110 | * 111 | * @param list 导出的实体集合 112 | * @param fileName 导出的文件名 113 | * @param pojoClass pojo实体 114 | * @param exportParams ExportParams封装实体 115 | * @param response 116 | * @return 117 | */ 118 | private static void defaultExport(List list, Class pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) { 119 | Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list); 120 | if (workbook != null) { 121 | downLoadExcel(fileName, response, workbook); 122 | } 123 | } 124 | 125 | /** 126 | * 功能描述:Excel导出 127 | * 128 | * @param fileName 文件名称 129 | * @param response 130 | * @param workbook Excel对象 131 | * @return 132 | */ 133 | public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) { 134 | try { 135 | response.setCharacterEncoding("UTF-8"); 136 | response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); 137 | response.setHeader("content-Type", "application/vnd.ms-excel"); 138 | response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); 139 | workbook.write(response.getOutputStream()); 140 | } catch (IOException e) { 141 | throw new RuntimeException(e); 142 | } 143 | } 144 | 145 | /** 146 | * 功能描述:默认导出方法 147 | * 148 | * @param list 导出的实体集合 149 | * @param fileName 导出的文件名 150 | * @param response 151 | * @return 152 | */ 153 | private static void defaultExport(List> list, String fileName, HttpServletResponse response) { 154 | Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF); 155 | if (workbook != null) { 156 | downLoadExcel(fileName, response, workbook); 157 | } 158 | } 159 | 160 | /** 161 | * 功能描述:根据文件路径来导入Excel 162 | * 163 | * @param filePath 文件路径 164 | * @param titleRows 表标题的行数--对应数据对象 165 | * @param headerRows 表头行数 166 | * @param pojoClass Excel实体类 167 | * @return 168 | */ 169 | public static List importExcel(String filePath, Integer titleRows, Integer headerRows, Class pojoClass) { 170 | //判断文件是否存在 171 | if (StringUtils.isBlank(filePath)) { 172 | return null; 173 | } 174 | ImportParams params = new ImportParams(); 175 | params.setTitleRows(titleRows); 176 | params.setHeadRows(headerRows); 177 | List list = null; 178 | try { 179 | list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params); 180 | } catch (NoSuchElementException e) { 181 | throw new RuntimeException("模板不能为空"); 182 | } catch (Exception e) { 183 | e.printStackTrace(); 184 | } 185 | return list; 186 | } 187 | 188 | /** 189 | * 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类 190 | * 191 | * @param file 上传的文件 192 | * @param titleRows 表标题的行数 193 | * @param headerRows 表头行数 194 | * @param pojoClass Excel实体类 195 | * @return 196 | */ 197 | public static List importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class pojoClass) { 198 | if (file == null) { 199 | return null; 200 | } 201 | ImportParams params = new ImportParams(); 202 | params.setTitleRows(titleRows); 203 | params.setHeadRows(headerRows); 204 | List list = null; 205 | try { 206 | list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params); 207 | } catch (NoSuchElementException e) { 208 | throw new RuntimeException("excel文件不能为空"); 209 | } catch (Exception e) { 210 | throw new RuntimeException(e.getMessage()); 211 | } 212 | return list; 213 | } 214 | 215 | /** 216 | * 功能描述:根据接收的Excel文件来导入多个sheet,根据索引可返回一个集合 217 | * @param filePath 导入文件路径 218 | * @param sheetIndex 导入sheet索引 219 | * @param titleRows 表标题的行数 220 | * @param headerRows 表头行数 221 | * @param pojoClass Excel实体类 222 | * @return 223 | */ 224 | public static List importExcel(String filePath,int sheetIndex,Integer titleRows, Integer headerRows, Class pojoClass) { 225 | // 根据file得到Workbook,主要是要根据这个对象获取,传过来的excel有几个sheet页 226 | ImportParams params = new ImportParams(); 227 | // 第几个sheet页 228 | params.setStartSheetIndex(sheetIndex); 229 | params.setTitleRows(titleRows); 230 | params.setHeadRows(headerRows); 231 | List list = null; 232 | try { 233 | list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params); 234 | } catch (NoSuchElementException e) { 235 | throw new RuntimeException("模板不能为空"); 236 | } catch (Exception e) { 237 | e.printStackTrace(); 238 | } 239 | return list; 240 | } 241 | 242 | /** 243 | * 功能描述:根据接收的Excel文件来导入多个sheet,根据索引可返回一个集合 244 | * @param list 实体对象集合 245 | * @param type 表格类型 246 | * @return 247 | */ 248 | public static Workbook exportExcel(List> list, ExcelType type) { 249 | Workbook workbook = getWorkbook(type, 0); 250 | Iterator var3 = list.iterator(); 251 | 252 | while(var3.hasNext()) { 253 | Map map = (Map)var3.next(); 254 | ExcelExportService service = new ExcelExportService(); 255 | service.createSheet(workbook, (ExportParams)map.get("title"), (Class)map.get("entity"), (Collection)map.get("data")); 256 | } 257 | return workbook; 258 | } 259 | private static Workbook getWorkbook(ExcelType type, int size) { 260 | if (ExcelType.HSSF.equals(type)) { 261 | return new HSSFWorkbook(); 262 | } else { 263 | return (Workbook)(size < USE_SXSSF_LIMIT ? new XSSFWorkbook() : new SXSSFWorkbook()); 264 | } 265 | } 266 | 267 | 268 | } 269 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/Json.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.util.Map; 8 | 9 | public class Json { 10 | 11 | private static ObjectMapper defaultObjectMapper = new ObjectMapper(); 12 | 13 | 14 | public static String toJacksonStr(Object obj) { 15 | String content = ""; 16 | try { 17 | content = defaultObjectMapper.writeValueAsString(obj); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | return ""; 21 | } 22 | return content; 23 | } 24 | 25 | public static T jsonToObject(Class type,String jsonStr) { 26 | try { 27 | return defaultObjectMapper.readValue(jsonStr,type); 28 | } catch (Exception e) { 29 | e.printStackTrace(); 30 | return null; 31 | } 32 | } 33 | 34 | /** 35 | * 把一个类型的数据转换为另一个类型的数据 36 | * 37 | * @param data 输入数据 38 | * @param type 转换的目标类型, 可传入com.fasterxml.jackson.databind.JavaType类型, 用于处理泛型 39 | */ 40 | public static T conversion(Object data, Class type) { 41 | try { 42 | if (data instanceof InputStream) { 43 | Map map = defaultObjectMapper.readValue((InputStream) data, Map.class); 44 | data = defaultObjectMapper.writeValueAsString(map); 45 | } 46 | String stringValue = null; 47 | if (data instanceof String) { 48 | stringValue = (String) data; 49 | } else { 50 | stringValue = defaultObjectMapper.writeValueAsString(data); 51 | } 52 | T newData = defaultObjectMapper.readValue(stringValue, type); 53 | return newData; 54 | } catch (IOException e) { 55 | throw new IllegalArgumentException(e); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationFeature; 6 | import com.fasterxml.jackson.databind.JavaType; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.google.common.reflect.TypeToken; 9 | import com.google.gson.Gson; 10 | import com.google.gson.GsonBuilder; 11 | import com.google.gson.JsonElement; 12 | import com.google.gson.JsonParser; 13 | 14 | import java.io.IOException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * json工具类 21 | * 22 | * @author lgl 23 | */ 24 | @SuppressWarnings("deprecation") 25 | public class JsonUtils { 26 | private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 27 | 28 | private JsonUtils() { 29 | 30 | } 31 | 32 | public static ObjectMapper getInstance() { 33 | return OBJECT_MAPPER; 34 | } 35 | 36 | /** 37 | * javaBean、列表数组转换为json字符串 38 | */ 39 | public static String obj2json(Object obj) { 40 | String returnData; 41 | try { 42 | returnData = OBJECT_MAPPER.writeValueAsString(obj); 43 | } catch (Exception e) { 44 | returnData = ""; 45 | } 46 | return returnData; 47 | } 48 | 49 | /** 50 | * javaBean、列表数组转换为json字符串,忽略空值 51 | */ 52 | public static String obj2jsonIgnoreNull(Object obj) throws Exception { 53 | OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); 54 | return OBJECT_MAPPER.writeValueAsString(obj); 55 | } 56 | 57 | /** 58 | * json 转JavaBean 59 | */ 60 | 61 | public static T json2pojo(String jsonString, Class clazz) throws Exception { 62 | OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 63 | OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 64 | return OBJECT_MAPPER.readValue(jsonString, clazz); 65 | } 66 | 67 | /** 68 | * json字符串转换为map,转后map类型是key:value形式 69 | */ 70 | public static Map json2map(String jsonString) { 71 | if (jsonString != null) { 72 | OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); 73 | try { 74 | return OBJECT_MAPPER.readValue(jsonString, Map.class); 75 | } catch (JsonProcessingException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | return null; 80 | } 81 | 82 | /** 83 | * json 转 map对象,转后的map对象是key=value形式 84 | * */ 85 | public static Map fromJsonStr(String json) { 86 | Gson gson = new Gson(); 87 | Map infoMap = gson.fromJson(json, 88 | new TypeToken>() { 89 | }.getType()); 90 | return infoMap; 91 | } 92 | 93 | /** 94 | * 深度转换json成map 95 | * 96 | * @param json 97 | * @return 98 | */ 99 | public static Map json2mapDeeply(String json) throws Exception { 100 | return json2MapRecursion(json, OBJECT_MAPPER); 101 | } 102 | 103 | /** 104 | * 把json解析成list,如果list内部的元素存在jsonString,继续解析 105 | * 106 | * @param json 107 | * @param mapper 解析工具 108 | * @return 109 | * @throws Exception 110 | */ 111 | private static List json2ListRecursion(String json, ObjectMapper mapper) throws Exception { 112 | if (json == null) { 113 | return null; 114 | } 115 | List list = mapper.readValue(json, List.class); 116 | for (Object obj : list) { 117 | if (obj != null && obj instanceof String) { 118 | String str = (String) obj; 119 | if (str.startsWith("[")) { 120 | obj = json2ListRecursion(str, mapper); 121 | } else if (obj.toString().startsWith("{")) { 122 | obj = json2MapRecursion(str, mapper); 123 | } 124 | } 125 | } 126 | 127 | return list; 128 | } 129 | 130 | /** 131 | * 把json解析成map,如果map内部的value存在jsonString,继续解析 132 | * 133 | * @param json 134 | * @param mapper 135 | * @return 136 | * @throws Exception 137 | */ 138 | private static Map json2MapRecursion(String json, ObjectMapper mapper) throws Exception { 139 | if (json == null) { 140 | return null; 141 | } 142 | Map map = mapper.readValue(json, Map.class); 143 | for (Map.Entry entry : map.entrySet()) { 144 | Object obj = entry.getValue(); 145 | if (obj != null && obj instanceof String) { 146 | String str = ((String) obj); 147 | if (str.startsWith("[")) { 148 | List list = json2ListRecursion(str, mapper); 149 | map.put(entry.getKey(), list); 150 | } else if (str.startsWith("{")) { 151 | Map mapRecursion = json2MapRecursion(str, mapper); 152 | map.put(entry.getKey(), mapRecursion); 153 | } 154 | } 155 | } 156 | return map; 157 | } 158 | 159 | /** 160 | * 与javaBean json数组字符串转换为列表 161 | */ 162 | public static List json2list(String jsonArrayStr, Class clazz) { 163 | OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 164 | JavaType javaType = getCollectionType(ArrayList.class, clazz); 165 | List lst = new ArrayList<>(); 166 | try { 167 | lst = OBJECT_MAPPER.readValue(jsonArrayStr, javaType); 168 | } catch (IOException e) { 169 | e.printStackTrace(); 170 | } 171 | return lst; 172 | } 173 | 174 | 175 | /** 176 | * 获取泛型的Collection Type 177 | * 178 | * @param collectionClass 泛型的Collection 179 | * @param elementClasses 元素类 180 | * @return JavaType Java类型 181 | * @since 1.0 182 | */ 183 | public static JavaType getCollectionType(Class collectionClass, Class... elementClasses) { 184 | return OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses); 185 | } 186 | 187 | 188 | /** 189 | * map 转JavaBean 190 | */ 191 | public static T map2pojo(Map map, Class clazz) { 192 | return OBJECT_MAPPER.convertValue(map, clazz); 193 | } 194 | 195 | /** 196 | * map 转json 197 | * 198 | * @param map 199 | * @return 200 | */ 201 | public static String mapToJson(Map map) { 202 | try { 203 | return OBJECT_MAPPER.writeValueAsString(map); 204 | } catch (Exception e) { 205 | e.printStackTrace(); 206 | } 207 | return ""; 208 | } 209 | 210 | /** 211 | * map 转JavaBean 212 | */ 213 | public static T obj2pojo(Object obj, Class clazz) { 214 | return OBJECT_MAPPER.convertValue(obj, clazz); 215 | } 216 | 217 | /** 218 | *序列化:将Java对象转换成JSON字符串 219 | * */ 220 | public static String jsonFormatter(String uglyJSONString){ 221 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 222 | JsonParser jp = new JsonParser(); 223 | JsonElement je = jp.parse(uglyJSONString); 224 | String prettyJsonString = gson.toJson(je); 225 | return prettyJsonString; 226 | } 227 | 228 | } 229 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/LoadStaticConfigUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; 4 | import org.springframework.core.io.ClassPathResource; 5 | import org.springframework.core.io.Resource; 6 | 7 | import java.util.Properties; 8 | 9 | public class LoadStaticConfigUtil { 10 | public static Object getCommonYml(Object key){ 11 | Resource resource = new ClassPathResource("/application-dev.yml"); 12 | Properties properties = null; 13 | try { 14 | YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); 15 | yamlFactory.setResources(resource); 16 | properties = yamlFactory.getObject(); 17 | } catch (Exception e) { 18 | e.printStackTrace(); 19 | return null; 20 | } 21 | return properties.get(key); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/Log4jUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import org.apache.log4j.Level; 4 | import org.apache.log4j.Logger; 5 | 6 | public class Log4jUtil { 7 | public static void info(Object str_info) { 8 | StackTraceElement stack[] = (new Throwable()).getStackTrace(); 9 | Logger logger = Logger.getLogger(stack[1].getClassName()); 10 | logger.log(Log4jUtil.class.getName(), Level.INFO, str_info, null); 11 | } 12 | 13 | public static void error(Object str_err) { 14 | StackTraceElement stack[] = (new Throwable()).getStackTrace(); 15 | Logger logger = Logger.getLogger(stack[1].getClassName()); 16 | logger.log(Log4jUtil.class.getName(), Level.ERROR, str_err, null); 17 | } 18 | 19 | public static void debug(Object str_debug) { 20 | StackTraceElement stack[] = (new Throwable()).getStackTrace(); 21 | Logger logger = Logger.getLogger(stack[1].getClassName()); 22 | logger.log(Log4jUtil.class.getName(), Level.DEBUG, str_debug, null); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/RandomDataKit.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import com.javaelf.data.CardIDGenerator; 4 | import com.javaelf.data.CharNumberGenerator; 5 | import com.javaelf.data.RandomGenerator; 6 | 7 | import java.text.SimpleDateFormat; 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | 15 | public class RandomDataKit { 16 | 17 | public static String randomDataStringInspect(String dataString){ 18 | String pattern = "Random\\(.+?\\)"; 19 | // String str = "{name : 'test' , age: 'Random(Long[2])' , detail: 'Random(String[50,60])' , isStudent: 'Random(Boolean)' }"; 20 | Pattern r = Pattern.compile(pattern); 21 | Matcher m = r.matcher(dataString); 22 | while (m.find()){ 23 | String randomStr = m.group(); 24 | Object randomVal = RandomDataKit.ranDomData(randomStr); 25 | try { 26 | dataString = dataString.replace(randomStr,randomVal.toString()); 27 | }catch (Exception ex){ 28 | ex.printStackTrace(); 29 | } 30 | 31 | } 32 | return dataString; 33 | } 34 | /** 35 | * 36 | * Random(String[0,10]) 37 | * Random(Char[10) 38 | * Random(Long[10]) 39 | * Random(Boolean) 40 | * Random(IDCard[19990909]) 41 | * Random(Date[yyyy-MM-dd hh:mm:ss]) 42 | * @param data 43 | * @return 44 | */ 45 | public static Object ranDomData(String data){ 46 | String pattern = "\\d+"; 47 | Pattern r = Pattern.compile(pattern); 48 | if(data.contains("String")){ 49 | Matcher m = r.matcher(data); 50 | List doorsill = new ArrayList<>(); 51 | while (m.find()){ 52 | doorsill.add(Integer.valueOf(m.group())); 53 | } 54 | return dataGenreate("String",doorsill); 55 | }else if(data.contains("Char")){ 56 | Matcher m = r.matcher(data); 57 | List doorsill = new ArrayList<>(); 58 | while (m.find()){ 59 | doorsill.add(Integer.valueOf(m.group())); 60 | } 61 | return dataGenreate("Char",doorsill); 62 | }else if(data.contains("Long")){ 63 | Matcher m = r.matcher(data); 64 | List doorsill = new ArrayList<>(); 65 | while (m.find()){ 66 | doorsill.add(Integer.valueOf(m.group())); 67 | } 68 | return dataGenreate("Long",doorsill); 69 | }else if(data.contains("Boolean")){ 70 | return dataGenreate("Boolean",null); 71 | }else if(data.contains("Date")){ 72 | pattern = "(?<=\\[).*?(?=\\])"; 73 | Pattern rDate = Pattern.compile(pattern); 74 | Matcher m = rDate.matcher(data); 75 | List doorsill = new ArrayList<>(); 76 | while (m.find()){ 77 | doorsill.add(m.group()); 78 | } 79 | return dataGenreate("Date",doorsill); 80 | } else if(data.contains("IDCard")){ 81 | pattern = "(?<=\\[).*?(?=\\])"; 82 | Pattern rDate = Pattern.compile(pattern); 83 | Matcher m = rDate.matcher(data); 84 | List doorsill = new ArrayList<>(); 85 | while (m.find()){ 86 | doorsill.add(m.group()); 87 | } 88 | return doorsill.size()>0 ? dataGenreate("IDCard",doorsill) : CardIDGenerator.IdNumber(null); 89 | } else{ 90 | return dataGenreate("not",null); 91 | } 92 | } 93 | 94 | /** 95 | * 96 | * @param type 数据类型 97 | * @param doorsill 数据区间 98 | * @return 99 | */ 100 | private static Object dataGenreate(String type,List doorsill){ 101 | Object obj = null; 102 | if (doorsill !=null && doorsill.size() == 1) { 103 | doorsill.add(doorsill.get(0)); 104 | } 105 | switch (type){ 106 | case "String": 107 | obj = CharNumberGenerator.generateInRadomLengthJianHan(Integer.parseInt(doorsill.get(0).toString()),Integer.parseInt(doorsill.get(1).toString())); 108 | break; 109 | case "Char": 110 | obj = CharNumberGenerator.generateLetter(Integer.parseInt(doorsill.get(0).toString()),Integer.parseInt(doorsill.get(1).toString())); 111 | break; 112 | case "Long": 113 | obj = CharNumberGenerator.generateLong(Integer.parseInt(doorsill.get(0).toString()),Integer.parseInt(doorsill.get(1).toString())); 114 | break; 115 | case "Boolean": 116 | obj = RandomGenerator.getRandomBoolean(); 117 | break; 118 | case "Date": 119 | obj = new SimpleDateFormat(doorsill.get(0).toString()).format(new Date()); 120 | break; 121 | case "IDCard": 122 | obj = CardIDGenerator.IdNumber(doorsill.get(0).toString()); 123 | break; 124 | default: 125 | obj = CharNumberGenerator.generateLetterAndInt(Integer.parseInt(doorsill.get(0).toString())); 126 | break; 127 | } 128 | return obj; 129 | } 130 | } 131 | 132 | -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/SpringContextUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * spring上下文 7 | * 8 | * @author yss 9 | * @date 2020-07-03 10 | */ 11 | public class SpringContextUtil { 12 | private static ApplicationContext applicationContext; 13 | 14 | /** 15 | * 获取上下文 16 | * 17 | * @return 18 | */ 19 | public static ApplicationContext getApplicationContext() { 20 | return applicationContext; 21 | } 22 | 23 | /** 24 | * 设置上下文 25 | * 26 | * @param applicationContext 27 | */ 28 | public static void setApplicationContext(ApplicationContext applicationContext) { 29 | com.javaelf.utils.SpringContextUtil.applicationContext = applicationContext; 30 | } 31 | 32 | /** 33 | * 通过名字获取上下文中的bean 34 | * 35 | * @param name 36 | * @return 37 | */ 38 | public static Object getBean(String name){ 39 | return applicationContext.getBean(name); 40 | } 41 | 42 | /** 43 | * 通过类型获取上下文中的bean 44 | * 45 | * @param requiredType 46 | * @return 47 | */ 48 | public static Object getBean(Class requiredType){ 49 | return applicationContext.getBean(requiredType); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/com/javaelf/utils/VariableUtil.java: -------------------------------------------------------------------------------- 1 | package com.javaelf.utils; 2 | 3 | 4 | import com.javaelf.dao.VariableSubstitutionDao; 5 | import com.javaelf.entity.VariableSubstitution; 6 | import java.lang.reflect.Method; 7 | import java.util.*; 8 | 9 | /** 10 | * 变量名替换变量值工具类 11 | * 读取测试数据中的变量数据把变量名替换为变量值 12 | */ 13 | public class VariableUtil { 14 | /*=========================================变量替换后进行数据库操作回写====================================*/ 15 | /** 16 | * 接收数待转换变量集合 17 | * 18 | * @return 19 | */ 20 | public static Map loadVariableToMap(List list,VariableSubstitutionDao variableSubstitutionDao) { 21 | Map variablelistMap = new HashMap<>(); 22 | for (VariableSubstitution variable : list) { 23 | String variableName = variable.getName(); 24 | String variableValue = variable.getValue(); 25 | //如果variableValue为null或""判断 26 | if (variableValue == null || variableValue.trim().length() == 0) { 27 | //获得要反射的类(得到反射类的全路径) 28 | String reflectCalss = variable.getReflectCalss(); 29 | //要反射调用的方法 30 | String reflectMethod = variable.getReflectMethod(); 31 | try { 32 | //获取字节码 33 | Class clzss = Class.forName(reflectCalss); 34 | //字节码对象 35 | Object object = clzss.newInstance(); 36 | //获取反射调用方法对象 37 | Method method = clzss.getMethod(reflectMethod); 38 | //反射调用方式,获取到方法的返回值 39 | variableValue = (String) method.invoke(object); 40 | variableSubstitutionDao.updateVariableValue(variableValue, variableName); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | variablelistMap.put(variableName, variableValue); 46 | } 47 | return variablelistMap; 48 | } 49 | 50 | /** 51 | * 变量转换成变量值 52 | * 53 | * @param parameter :需要替换的变量名 54 | */ 55 | public static String replaceVariables(String parameter, List variableSubstitutionList,VariableSubstitutionDao variableSubstitutionDao) { 56 | Map variablelistMap = loadVariableToMap(variableSubstitutionList,variableSubstitutionDao); 57 | //取出所有的变量名 58 | Set variableNames = variablelistMap.keySet(); 59 | if (parameter != null) { 60 | for (String variableName : variableNames) { 61 | //判断测试数据中出现了变量名就执行替换变量值的操作 62 | if (parameter.contains(variableName)) { 63 | parameter = parameter.replace(variableName, (CharSequence) variablelistMap.get(variableName)); 64 | } 65 | } 66 | } 67 | return parameter; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/hibernate/cfg/PropertyContainer.java: -------------------------------------------------------------------------------- 1 | package org.hibernate.cfg; 2 | 3 | import org.hibernate.AnnotationException; 4 | import org.hibernate.annotations.Any; 5 | import org.hibernate.annotations.ManyToAny; 6 | import org.hibernate.annotations.Target; 7 | import org.hibernate.annotations.Type; 8 | import org.hibernate.annotations.common.reflection.XClass; 9 | import org.hibernate.annotations.common.reflection.XProperty; 10 | import org.hibernate.boot.MappingException; 11 | import org.hibernate.boot.jaxb.Origin; 12 | import org.hibernate.boot.jaxb.SourceType; 13 | import org.hibernate.cfg.annotations.HCANNHelper; 14 | import org.hibernate.internal.CoreMessageLogger; 15 | import org.hibernate.internal.util.StringHelper; 16 | import org.jboss.logging.Logger; 17 | 18 | import javax.persistence.*; 19 | import java.util.*; 20 | 21 | /** 22 | * 解决数据实体对象创建表乱序问题 23 | * 24 | */ 25 | class PropertyContainer { 26 | private static final CoreMessageLogger LOG = (CoreMessageLogger) Logger.getMessageLogger(CoreMessageLogger.class, PropertyContainer.class.getName()); 27 | private final XClass xClass; 28 | private final XClass entityAtStake; 29 | private final AccessType classLevelAccessType; 30 | private final LinkedHashMap persistentAttributeMap; 31 | 32 | PropertyContainer(XClass clazz, XClass entityAtStake, AccessType defaultClassLevelAccessType) { 33 | this.xClass = clazz; 34 | this.entityAtStake = entityAtStake; 35 | if (defaultClassLevelAccessType == AccessType.DEFAULT) { 36 | defaultClassLevelAccessType = AccessType.PROPERTY; 37 | } 38 | 39 | AccessType localClassLevelAccessType = this.determineLocalClassDefinedAccessStrategy(); 40 | 41 | assert localClassLevelAccessType != null; 42 | 43 | this.classLevelAccessType = localClassLevelAccessType != AccessType.DEFAULT ? localClassLevelAccessType : defaultClassLevelAccessType; 44 | 45 | assert this.classLevelAccessType == AccessType.FIELD || this.classLevelAccessType == AccessType.PROPERTY; 46 | 47 | this.persistentAttributeMap = new LinkedHashMap(); 48 | List fields = this.xClass.getDeclaredProperties(AccessType.FIELD.getType()); 49 | List getters = this.xClass.getDeclaredProperties(AccessType.PROPERTY.getType()); 50 | this.preFilter(fields, getters); 51 | Map persistentAttributesFromGetters = new HashMap(); 52 | this.collectPersistentAttributesUsingLocalAccessType(this.persistentAttributeMap, persistentAttributesFromGetters, fields, getters); 53 | this.collectPersistentAttributesUsingClassLevelAccessType(this.persistentAttributeMap, persistentAttributesFromGetters, fields, getters); 54 | } 55 | 56 | private void preFilter(List fields, List getters) { 57 | Iterator propertyIterator = fields.iterator(); 58 | 59 | XProperty property; 60 | while(propertyIterator.hasNext()) { 61 | property = (XProperty)propertyIterator.next(); 62 | if (mustBeSkipped(property)) { 63 | propertyIterator.remove(); 64 | } 65 | } 66 | 67 | propertyIterator = getters.iterator(); 68 | 69 | while(propertyIterator.hasNext()) { 70 | property = (XProperty)propertyIterator.next(); 71 | if (mustBeSkipped(property)) { 72 | propertyIterator.remove(); 73 | } 74 | } 75 | 76 | } 77 | 78 | private void collectPersistentAttributesUsingLocalAccessType(LinkedHashMap persistentAttributeMap, Map persistentAttributesFromGetters, List fields, List getters) { 79 | Iterator propertyIterator = fields.iterator(); 80 | 81 | XProperty xProperty; 82 | Access localAccessAnnotation; 83 | while(propertyIterator.hasNext()) { 84 | xProperty = (XProperty)propertyIterator.next(); 85 | localAccessAnnotation = (Access)xProperty.getAnnotation(Access.class); 86 | if (localAccessAnnotation != null && localAccessAnnotation.value() == javax.persistence.AccessType.FIELD) { 87 | propertyIterator.remove(); 88 | persistentAttributeMap.put(xProperty.getName(), xProperty); 89 | } 90 | } 91 | 92 | propertyIterator = getters.iterator(); 93 | 94 | while(propertyIterator.hasNext()) { 95 | xProperty = (XProperty)propertyIterator.next(); 96 | localAccessAnnotation = (Access)xProperty.getAnnotation(Access.class); 97 | if (localAccessAnnotation != null && localAccessAnnotation.value() == javax.persistence.AccessType.PROPERTY) { 98 | propertyIterator.remove(); 99 | String name = xProperty.getName(); 100 | XProperty previous = (XProperty)persistentAttributesFromGetters.get(name); 101 | if (previous != null) { 102 | throw new MappingException(LOG.ambiguousPropertyMethods(this.xClass.getName(), HCANNHelper.annotatedElementSignature(previous), HCANNHelper.annotatedElementSignature(xProperty)), new Origin(SourceType.ANNOTATION, this.xClass.getName())); 103 | } 104 | 105 | persistentAttributeMap.put(name, xProperty); 106 | persistentAttributesFromGetters.put(name, xProperty); 107 | } 108 | } 109 | 110 | } 111 | 112 | private void collectPersistentAttributesUsingClassLevelAccessType(LinkedHashMap persistentAttributeMap, Map persistentAttributesFromGetters, List fields, List getters) { 113 | Iterator var5; 114 | XProperty getter; 115 | if (this.classLevelAccessType == AccessType.FIELD) { 116 | var5 = fields.iterator(); 117 | 118 | while(var5.hasNext()) { 119 | getter = (XProperty)var5.next(); 120 | if (!persistentAttributeMap.containsKey(getter.getName())) { 121 | persistentAttributeMap.put(getter.getName(), getter); 122 | } 123 | } 124 | } else { 125 | var5 = getters.iterator(); 126 | 127 | while(var5.hasNext()) { 128 | getter = (XProperty)var5.next(); 129 | String name = getter.getName(); 130 | XProperty previous = (XProperty)persistentAttributesFromGetters.get(name); 131 | if (previous != null) { 132 | throw new MappingException(LOG.ambiguousPropertyMethods(this.xClass.getName(), HCANNHelper.annotatedElementSignature(previous), HCANNHelper.annotatedElementSignature(getter)), new Origin(SourceType.ANNOTATION, this.xClass.getName())); 133 | } 134 | 135 | if (!persistentAttributeMap.containsKey(name)) { 136 | persistentAttributeMap.put(getter.getName(), getter); 137 | persistentAttributesFromGetters.put(name, getter); 138 | } 139 | } 140 | } 141 | 142 | } 143 | 144 | public XClass getEntityAtStake() { 145 | return this.entityAtStake; 146 | } 147 | 148 | public XClass getDeclaringClass() { 149 | return this.xClass; 150 | } 151 | 152 | public AccessType getClassLevelAccessType() { 153 | return this.classLevelAccessType; 154 | } 155 | 156 | public Collection getProperties() { 157 | this.assertTypesAreResolvable(); 158 | return Collections.unmodifiableCollection(this.persistentAttributeMap.values()); 159 | } 160 | 161 | private void assertTypesAreResolvable() { 162 | Iterator var1 = this.persistentAttributeMap.values().iterator(); 163 | 164 | XProperty xProperty; 165 | do { 166 | if (!var1.hasNext()) { 167 | return; 168 | } 169 | 170 | xProperty = (XProperty)var1.next(); 171 | } while(xProperty.isTypeResolved() || discoverTypeWithoutReflection(xProperty)); 172 | 173 | String msg = "Property " + StringHelper.qualify(this.xClass.getName(), xProperty.getName()) + " has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type"; 174 | throw new AnnotationException(msg); 175 | } 176 | 177 | private AccessType determineLocalClassDefinedAccessStrategy() { 178 | AccessType hibernateDefinedAccessType = AccessType.DEFAULT; 179 | AccessType jpaDefinedAccessType = AccessType.DEFAULT; 180 | org.hibernate.annotations.AccessType accessType = (org.hibernate.annotations.AccessType)this.xClass.getAnnotation(org.hibernate.annotations.AccessType.class); 181 | if (accessType != null) { 182 | hibernateDefinedAccessType = AccessType.getAccessStrategy(accessType.value()); 183 | } 184 | 185 | Access access = (Access)this.xClass.getAnnotation(Access.class); 186 | if (access != null) { 187 | jpaDefinedAccessType = AccessType.getAccessStrategy(access.value()); 188 | } 189 | 190 | if (hibernateDefinedAccessType != AccessType.DEFAULT && jpaDefinedAccessType != AccessType.DEFAULT && hibernateDefinedAccessType != jpaDefinedAccessType) { 191 | throw new org.hibernate.MappingException("@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. "); 192 | } else { 193 | AccessType classDefinedAccessType; 194 | if (hibernateDefinedAccessType != AccessType.DEFAULT) { 195 | classDefinedAccessType = hibernateDefinedAccessType; 196 | } else { 197 | classDefinedAccessType = jpaDefinedAccessType; 198 | } 199 | 200 | return classDefinedAccessType; 201 | } 202 | } 203 | 204 | private static boolean discoverTypeWithoutReflection(XProperty p) { 205 | if (p.isAnnotationPresent(OneToOne.class) && !((OneToOne)p.getAnnotation(OneToOne.class)).targetEntity().equals(Void.TYPE)) { 206 | return true; 207 | } else if (p.isAnnotationPresent(OneToMany.class) && !((OneToMany)p.getAnnotation(OneToMany.class)).targetEntity().equals(Void.TYPE)) { 208 | return true; 209 | } else if (p.isAnnotationPresent(ManyToOne.class) && !((ManyToOne)p.getAnnotation(ManyToOne.class)).targetEntity().equals(Void.TYPE)) { 210 | return true; 211 | } else if (p.isAnnotationPresent(ManyToMany.class) && !((ManyToMany)p.getAnnotation(ManyToMany.class)).targetEntity().equals(Void.TYPE)) { 212 | return true; 213 | } else if (p.isAnnotationPresent(Any.class)) { 214 | return true; 215 | } else if (p.isAnnotationPresent(ManyToAny.class)) { 216 | if (!p.isCollection() && !p.isArray()) { 217 | throw new AnnotationException("@ManyToAny used on a non collection non array property: " + p.getName()); 218 | } else { 219 | return true; 220 | } 221 | } else if (p.isAnnotationPresent(Type.class)) { 222 | return true; 223 | } else { 224 | return p.isAnnotationPresent(Target.class); 225 | } 226 | } 227 | 228 | private static boolean mustBeSkipped(XProperty property) { 229 | return property.isAnnotationPresent(Transient.class) || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals(property.getType().getName()) || "org.hibernate.bytecode.internal.javassist.FieldHandler".equals(property.getType().getName()); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/main/resources/MindUML.puml: -------------------------------------------------------------------------------- 1 | @startmindmap 2 | 'https://plantuml.com/mindmap-diagram 3 | title 脑图 4 | 5 | * 根节点 6 | ** 节点1 7 | *** 节点11 8 | ** 节点2 9 | *** 节点22 10 | ** 节点3 11 | *** 节点33 12 | *** 节点34 13 | 14 | @endmindmap 15 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8091 3 | servlet: 4 | context-path: / 5 | 6 | logging: 7 | config: classpath:log4j2.xml 8 | 9 | spring: 10 | datasource: 11 | url: jdbc:mysql://localhost:3306/javaelf?Unicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=GMT 12 | username: root 13 | password: root 14 | driver-class-name: com.mysql.cj.jdbc.Driver 15 | type: com.alibaba.druid.pool.DruidDataSource 16 | druid: 17 | initial-size: 5 18 | min-idle: 5 19 | max-active: 20 20 | max-wait: 60000 21 | time-between-eviction-runs-millis: 60000 22 | min-evictable-idle-time-millis: 300000 23 | validation-query: SELECT 1 FROM DUAL 24 | test-while-idle: true 25 | test-on-borrow: false 26 | test-on-return: false 27 | pool-prepared-statements: true 28 | max-pool-prepared-statement-per-connection-size: 20 29 | filters: stat,wall 30 | web-stat-filter: 31 | enabled: true 32 | url-pattern: /* 33 | exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*' 34 | session-stat-enable: true 35 | session-stat-max-count: 10000 36 | principal-session-name: admin 37 | principal-cookie-name: admin 38 | profile-enable: true 39 | stat-view-servlet: 40 | enabled: true 41 | url-pattern: /druid/* 42 | reset-enable: true 43 | # login-username: hxplAdmin 44 | # login-password: hxpl@admin#20190315 45 | jpa: 46 | hibernate: 47 | ddl-auto: update 48 | #naming: 49 | # physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 50 | show-sql: true 51 | properties: 52 | hibernate: 53 | enable_lazy_load_no_trans: true 54 | 55 | # mail: 56 | # host: "smtp.qq.com" 57 | # username: "xxx" 58 | # password: "xxx" 59 | #test: 60 | # mail: 61 | # send: 62 | # cc: 63 | 64 | #定时任务配置 65 | #'index.job': '0 0 0 * * ?' 66 | #'thirdOrderCancel.job': '0 0/60 * * * ?' 67 | 'autoRefund.job': '0 0/60 * * * ?' 68 | #'deleteCosUploadImg.job': '0 0 * * * ?' 69 | 70 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: dev 4 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | elf 7 | 10 | %-5level %d{yyyy-MM-dd HH:mm:ss} [%t] %l - %msg%n 11 | 13 | INFO 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/main/resources/mock/have-paramaters-get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"这是一个带参数的get请求", 4 | "request":{ 5 | "uri":"/getdemo", 6 | "method":"get", 7 | "queries":{ 8 | "name":"czy", 9 | "age":"29" 10 | } 11 | }, 12 | "response":{ 13 | "text":"返回这是一个带参数的get请求", 14 | "headers":{ 15 | "Content-Type":"text/html;charset=gbk" 16 | } 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /src/main/resources/mock/have-paramaters-post-json.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "description":"这是一个带参数的post请求,请求参数格式是key:value,不能使用queries,要使用forms", 3 | "request":{ 4 | "uri":"/postjson", 5 | "method":"post", 6 | "json":{ 7 | "name":"czy", 8 | "age":"29" 9 | }}, 10 | "response":{ 11 | "json":{ 12 | "error":"1000", 13 | "mages":"success" 14 | }, 15 | "headers":{ 16 | "Content-Type":"application/json;charset=gbk" 17 | } 18 | } 19 | } 20 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/have-paramaters-post.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "description":"这是一个带参数的post请求,请求参数格式是key:value,不能使用queries,要使用forms", 3 | "request":{ 4 | "uri":"/postwithparam", 5 | "method":"post", 6 | "forms":{ 7 | "name":"czy", 8 | "age":"29" 9 | }}, 10 | "response":{ 11 | "text":"这是一个带表单参数的post请求", 12 | "headers":{ 13 | "Content-Type":"text/html;charset=gbk" 14 | } 15 | } 16 | } 17 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/json-paramaters-havecookies-post-2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求,json返回中有中文,json可以解析中文", 4 | "request":{ 5 | "uri":"/postwithcookiesandjsontwo", 6 | "method":"post", 7 | "cookies":{ 8 | "login":"true" 9 | }, 10 | "json":{ 11 | "name":"czy", 12 | "age":"29" 13 | } 14 | }, 15 | "response":{ 16 | "status":200, 17 | "json":{ 18 | "code":"0", 19 | "msg":"success", 20 | "p2pdata":{ 21 | "name":"北京", 22 | "address":"六道口" 23 | } 24 | 25 | } 26 | } 27 | } 28 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/json-paramaters-havecookies-post.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求", 4 | "request":{ 5 | "uri":"/postwithcookiesandjson", 6 | "method":"post", 7 | "cookies":{ 8 | "login":"true" 9 | }, 10 | "json":{ 11 | "name":"czy", 12 | "age":"29" 13 | } 14 | }, 15 | "response":{ 16 | "status":200, 17 | "json":{ 18 | "code":"0", 19 | "msg":"success", 20 | "p2pdata":{ 21 | "name":"czy", 22 | "address":"beijing" 23 | } 24 | 25 | } 26 | } 27 | } 28 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/json-paramaters-haveheaders-post.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"这是一个request请求中带cookies、使用json格式传参、返回结果为json格式的post请求,json返回中有中文,json可以解析中文", 4 | "request":{ 5 | "uri":"/postheaders", 6 | "method":"post", 7 | "headers":{ 8 | "token":"123456789%" 9 | }, 10 | "json":{ 11 | "name":"czy", 12 | "age":"29" 13 | } 14 | }, 15 | "response":{ 16 | "status":200, 17 | "json":{ 18 | "code":"0", 19 | "msg":"success", 20 | "data":{ 21 | "name":"北京", 22 | "address":"六道口" 23 | } 24 | } 25 | } 26 | } 27 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/no-paramaters-get-302.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"模拟重定向接口", 4 | "request":{ 5 | "uri":"/redirectto" 6 | }, 7 | "redirectTo":"/redirectedpath" 8 | }, 9 | { 10 | "description":"模拟被重定向的接口", 11 | "request":{ 12 | "uri":"/redirectedpath" 13 | }, 14 | "response":{ 15 | "text":"返回重定向结果", 16 | "headers":{ 17 | "Content-Type":"text/html;charset=gbk" 18 | } 19 | } 20 | } 21 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/no-paramaters-get-responsehavecookies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"模拟response返回中带有cookies信息的get请求", 4 | "request":{ 5 | "uri":"/getcookies" 6 | }, 7 | "response":{ 8 | "cookies":{ 9 | "login":"true", 10 | "token":"test-czy" 11 | 12 | }, 13 | "json":{ 14 | "name":"czy", 15 | "age":"29" 16 | } 17 | } 18 | } 19 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/no-paramaters-get1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "这是第一个moco操作,格式要写正确,中括号、大括号一定要有,description是描述,request是请求,uri是请求路径,response是返回结果,text是返回的是文本类型内容", 4 | "request": { 5 | "uri": "/demo" 6 | }, 7 | "response": { 8 | "text": "this is the noparame-get moco demo" 9 | } 10 | } 11 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/no-paramaters-get2.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"description":"这是第二个moco操作,模拟返回值为中文", 3 | "request":{ 4 | "uri":"/demotwo" 5 | }, 6 | "response":{ 7 | "text":"这是第二个demo", 8 | "headers":{ 9 | "Content-Type":"text/html;charset=gbk" 10 | } 11 | 12 | } 13 | } 14 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/no-paramaters-post.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "这是第一个moco操作,格式要写正确,中括号、大括号一定要有,description是描述,request是请求,uri是请求路径,response是返回结果,text是返回的是文本类型内容", 4 | "request": { 5 | "uri": "/demo" 6 | }, 7 | "response": { 8 | "text": "this is the noparame-post moco demo" 9 | } 10 | } 11 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/noparamaters-havecookies-get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description":"这是一个request请求中带cookies信息的get请求", 4 | "request":{ 5 | "uri":"/getwithcookies", 6 | "method":"get", 7 | "cookies":{ 8 | "login":"true" 9 | } 10 | }, 11 | "response":{ 12 | "text":"返回这是一个request请求中带cookies信息的get请求", 13 | "headers":{ 14 | "Content-Type":"text/html;charset=gbk" 15 | } 16 | } 17 | } 18 | ] -------------------------------------------------------------------------------- /src/main/resources/mock/readme.md: -------------------------------------------------------------------------------- 1 | ###### 附之前用到mock笔记存留 2 | 3 | - mock-runner使用说明 4 | 5 | - 1.什么是mock 6 | - Moco 是一个搭建模拟服务器的工具,其支持 API 和独立运行两种方式,前者通常是在 junit 、testng等测试框架中使用,后者则是通过运行一个 jar 包开启服务。 7 | 8 | - 2.Moco在开发中会起到的作用 9 | - Moco是针对HTTP集成而生的,不过,现在也有人把它用在其它需要一个模拟服务器的场景中。比如,在移动开发中,有人开发一个移动应用,需要有一个远端服务,但在开发时,这个服务还不存在,他就用Moco模拟了一个服务,保证移动应用可以顺利的开发。 10 | - 同样,也有人把它用在Web前端开发里,当我们的页面需要通过与服务器交互时,就可以用Moco模拟这样一个服务。这种做法在开发一个页面原型时,非常有用,因为那个时候,我们还来不及开发一个完整的服务。 11 | 12 | - 3.Moco在接口测试中的用处 13 | - 既然开发人员可以通过 Moco 模拟一个还不存在的服务来进行开发、调试,那对于接口测试来说,也可以模拟一个服务进行测试。 14 | - 一般而言,在项目的接口文档输出后,开发人员会进行接口开发工作,测试人员会进行接口用例的设计,但往往完成用例设计会先于接口开发工作,此时如果要进行接口用例的执行,则前提是开发人员完成接口开发工作。 15 | - 而通过 Moco 框架,就可以在接口文档输出后,在接口开发、接口用例设计的同时,使用 Moco 搭建一个模拟服务器,这样在用例设计完成后,即使接口开发工作还未完成,也可以立即进行执行接口用例,在这个过程中可以修改、补充用例,如此的话,在接口开发完成以后,只需要简单的去执行所有的用例就 OK,省去了很大的工作量,并且这些完善的用例,用自动化去执行,效果更佳。 16 | 17 | - 4.Moco的应用 演示示例 18 | - 4.1.模拟get请求 19 | 20 | - 4.2.模拟带参数的get请求 21 | 22 | - 4.3.模拟post请求 23 | 24 | - 4.4.模拟带form格式参数的post请求 25 | 26 | - 4.5.模拟request请求中带cookies信息的get请求 27 | 28 | - 4.6.模拟request请求中带cookies的post请求,post请求带json格式参数,返回结果也使用json格式 29 | 30 | - 4.7.模拟response返回中带有cookies信息的get请求 31 | 32 | - 4.8.模拟带有headers信息的mock请求 33 | 34 | - 4.9.模拟有重定向的接口 35 | 36 | - 4.10使用httpclient调moco的接口 37 | - 以上示例代码在src.resource.mock.sample包下 38 | - 运行命令示例 39 | ``` 40 | java -jar moco-runner-0.11.0-standalone.jar http -p 8081 -c have-Paramatersget.json 41 | 42 | ``` -------------------------------------------------------------------------------- /src/main/resources/testcaseexcel/企业微信接口测试集.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CuiZhongyuan/Java-elf/1aaa1acfd8919e76183caafbfcfcff659597d2e1/src/main/resources/testcaseexcel/企业微信接口测试集.xls -------------------------------------------------------------------------------- /src/main/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/java/testcase/Algorithm.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import com.javaelf.utils.JsonUtils; 4 | import org.testng.annotations.Test; 5 | import org.testng.util.Strings; 6 | 7 | import java.util.*; 8 | 9 | public class Algorithm { 10 | int[] numss = {56,47,25,89,46,5,15,23}; 11 | 12 | //===================================二分查找,使用了递归调用========================== 13 | 14 | @Test 15 | public int binarySearch(int[] nums,int start,int end,int findnum){ 16 | if (start <= end) { 17 | //取出中间位置 18 | int binarynum = (start + end) / 2; 19 | //取中间位置的值 20 | int binarynumValue = nums[binarynum]; 21 | //判断 22 | if (findnum == binarynumValue) { 23 | return binarynum; 24 | } else if (findnum < binarynumValue) { 25 | return binarySearch(nums, start, binarynum - 1, findnum); 26 | } else { 27 | return binarySearch(nums, binarynum + 1, end, findnum); 28 | } 29 | } 30 | return -1; 31 | } 32 | 33 | @Test 34 | public void test(){ 35 | int[] nums = new int[100]; 36 | for (int i=0;i<100;i++){ 37 | nums[i] = (i+1); 38 | } 39 | int findnum = 25; 40 | int result = binarySearch(nums,0,nums.length-1,findnum); 41 | //查索引 42 | System.out.println(result+1); 43 | } 44 | 45 | 46 | 47 | @Test 48 | public void case1(){ 49 | int[] nums = {5,4,9,24,7,21,11,64,45,42}; 50 | //冒泡排序 51 | bubbleSort(nums); 52 | //选择排序 53 | selectSort(nums); 54 | } 55 | //==============================冒泡排序【重复走访要排序的数列,每次比较两个元素,如果顺序不对就进行交换,直到没有被交换的元素为止,这样就完成了一次冒泡排序】=========================== 56 | //调用冒泡排序方法 57 | private void bubbleSort(int[] nums) { 58 | for (int i=1 ;i nums[j+1]){ 61 | int temp = nums[j]; 62 | nums[j] =nums[j+1]; 63 | nums[j+1] = temp; 64 | } 65 | } 66 | } 67 | System.out.println(Arrays.toString(nums)); 68 | } 69 | 70 | //==============================选择排序【依次循环数组,每轮找出最小的值放到数组的最前面,直到循环结束就能得到一个有序数组】=========================== 71 | //调用选择排序 72 | private void selectSort(int[] nums) { 73 | int index; 74 | int temp; 75 | for (int i =0;i findNum) { 141 | return binarySearch(nums, 0, middlePosition - 1, findNum); 142 | } else { 143 | return binarySearch(nums, middlePosition + 1, i1, findNum); 144 | } 145 | } 146 | return -1; 147 | } 148 | 149 | //冒泡排序 150 | public void bubbleSort1(int[] nums){ 151 | int temp; 152 | for (int i=1;inums[j+1]){ 155 | temp=nums[j]; 156 | nums[j]=nums[j+1]; 157 | nums[j+1]=temp; 158 | } 159 | } 160 | } 161 | System.out.println(Arrays.toString(nums)); 162 | } 163 | 164 | @Test 165 | public void toLowerCase(){ 166 | String str = "ACCjkOOlKjhG"; 167 | System.out.println(str.toLowerCase(Locale.forLanguageTag(str))); 168 | } 169 | @Test 170 | public void toUpperCase(){ 171 | String str = " ACCjkOOjlKjhG "; 172 | System.out.println(str.toUpperCase(Locale.forLanguageTag(str))); 173 | System.out.println(str.length()); 174 | System.out.println(str.trim()); 175 | System.out.println(str.replaceAll("A","D")); 176 | String[] resout= str.split("j"); 177 | System.out.println(Arrays.toString(resout)); 178 | System.out.println(Strings.join(",",resout)); 179 | } 180 | 181 | 182 | //stream流去重 183 | @Test 184 | public void array(){ 185 | int[] numss = {56,47,25,47,56}; 186 | Set stringSet = new HashSet<>(); 187 | String num= "5,4,[1,2,4,4,5]"; 188 | int[] ints = Arrays.stream(numss).distinct().toArray(); 189 | System.out.println(Arrays.toString(ints)); 190 | num.replace("[",""); 191 | num.replace("]",""); 192 | String[] s = num.split(","); 193 | Object[] objects = Arrays.stream(s).distinct().toArray(); 194 | System.out.println(Arrays.toString(objects)); 195 | } 196 | 197 | @Test 198 | public void binarySearc2(){ 199 | int[] a = {1,2,4,4,5}; 200 | int findnum = 4; 201 | int result = upper_bound_(5,findnum,a); 202 | System.out.println(result); 203 | int result1 = binarySearch(a,0,5,findnum); 204 | System.out.println(result1+1); 205 | } 206 | /** 207 | * 二分查找 208 | * @param n int整型 数组长度 209 | * @param v int整型 查找值 210 | * @param a int整型一维数组 有序数组 211 | * @return int整型 212 | */ 213 | 214 | public int upper_bound_ (int n, int v, int[] a) { 215 | int right = n - 1; 216 | int left = 0; 217 | int middle = 0; 218 | 219 | // 循环不变量: 220 | // 若v能被找到,则保证v在[left, right]这个左闭右闭区间中 221 | while (left <= right) { 222 | int mid = left + (right - left) / 2; 223 | // mid处的值和v相等,但是它可能并不是数组中第一个v 224 | // 因此继续缩小查找范围,排除掉重复的元素 225 | if (a[mid] >= v) { 226 | right = mid - 1; 227 | } else { 228 | left = mid + 1; 229 | } 230 | } 231 | // 循环结束时left > right 232 | // 分为2种情况: 233 | // 情况1:找到v,此时left指向v 234 | // 情况2:未找到v,此时left指向v应该被插入的位置 235 | // 因为该题索引从1开始,因此返回值要加1 236 | return left + 1; 237 | } 238 | 239 | //利用Arrays中的Sort函数排序 240 | @Test 241 | public void ArraysSort() { 242 | Arrays.sort(numss); //默认升序排列 243 | for (int i = 0; i < numss.length; i++) { 244 | System.out.print(numss[i]+"、"); 245 | }} 246 | } 247 | -------------------------------------------------------------------------------- /src/test/java/testcase/ConcurrentTestCase.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | 4 | import com.javaelf.utils.JsonUtils; 5 | import com.javaelf.utils.RestTemplateUtils; 6 | import org.springframework.http.ResponseEntity; 7 | import org.testng.annotations.Test; 8 | import sun.misc.Lock; 9 | 10 | import java.text.SimpleDateFormat; 11 | import java.util.*; 12 | import java.util.concurrent.CyclicBarrier; 13 | import java.util.concurrent.ExecutorService; 14 | import java.util.concurrent.Executors; 15 | 16 | /** 17 | * @date 2020年4月28日 18 | * @author czy 19 | * 腾云核销并发测试 20 | */ 21 | public class ConcurrentTestCase { 22 | 23 | private List pass_numberList = new ArrayList() { 24 | { 25 | add("AA"); 26 | add("BB"); 27 | } 28 | }; 29 | private List sub_order_idList = new ArrayList(){ 30 | { 31 | add("aa"); 32 | add("bb"); 33 | } 34 | }; 35 | 36 | public void testSms(int n, int x) { 37 | int flag=n-1; 38 | System.out.println("###"+timeDate()+"###"+pass_numberList.get(flag)+"|" 39 | +sub_order_idList.get(flag)+"[并发线程"+flag+","+x+"--"+n+"]=>>>"+ty_4(pass_numberList.get(flag), sub_order_idList.get(flag))); 40 | } 41 | 42 | public String timeDate(){ 43 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); 44 | } 45 | 46 | //线程并发执行入口 47 | @Test 48 | public void cyclicbarrierTest() { 49 | //循环次数 50 | for (int x = 0; x < 1; x++) { 51 | NoThread noThread = new NoThread(); 52 | int count = 2;//并发量 53 | CyclicBarrier cyclicBarrier = new CyclicBarrier(count); 54 | ExecutorService executorService = Executors.newFixedThreadPool(count); 55 | for (int i = 0; i < count; i++) { 56 | executorService.execute(new Task(cyclicBarrier, noThread, x)); 57 | } 58 | executorService.shutdown(); 59 | while (!executorService.isTerminated()) { 60 | try { 61 | Thread.sleep(5); 62 | } catch (InterruptedException e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public class NoThread { 70 | Lock lock = new Lock(); 71 | int n = 0; 72 | int error = 0; 73 | int sccess = 0; 74 | 75 | public void add() throws InterruptedException { 76 | lock.lock(); 77 | ++n; 78 | lock.unlock(); 79 | } 80 | 81 | public void conet(String code) { 82 | if ("1".equals(code)) { 83 | sccess++; 84 | } else { 85 | error++; 86 | } 87 | System.out.println(sccess / (sccess + error) + "%"); 88 | } 89 | 90 | 91 | } 92 | 93 | public class Task implements Runnable { 94 | private CyclicBarrier cyclicBarrier; 95 | private NoThread noThread; 96 | private int x; 97 | 98 | public Task(CyclicBarrier cyclicBarrier, NoThread noThread, int x) { 99 | this.cyclicBarrier = cyclicBarrier; 100 | this.noThread = noThread; 101 | this.x = x; 102 | } 103 | 104 | @Override 105 | public void run() { 106 | try { 107 | // 等待所有任务准备就绪 108 | cyclicBarrier.await(); 109 | noThread.add(); 110 | testSms(noThread.n, x); 111 | 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | } 115 | } 116 | } 117 | 118 | 119 | /** 120 | * 腾云核销接口测试 委托票 普通票 组合票 121 | */ 122 | public String ty_4(String pass_number,String sub_order_id) { 123 | 124 | String url ="http://127.0.0.1:8090/jsonpost"; 125 | // Map map = new HashMap(); 126 | // String time = DateUtils.getSystime(); 127 | // // 资源id——tengyunGardenId 128 | // map.put("resource_id", "bf299f31-8ce9-474f-9f6d-367cc1952807"); 129 | // // 设备id——tengyunChannelId 130 | // map.put("device_id", "SPC00000001end"); 131 | // map.put("source_type",3); 132 | // map.put("source_id", "17093666626"); 133 | // map.put("timestamp", time); 134 | // map.put("nonce", "asdfasdfa"); 135 | // // 暂时不做签名校验 136 | // map.put("sign", ""); 137 | // Map mapc = new HashMap(); 138 | // //主单号 139 | // mapc.put("pass_number", pass_number); 140 | // // 当 人像扫描的时候 传 子订单号 141 | // mapc.put("sub_order_id", sub_order_id); 142 | // //输入类型3--扫码枪 4--人像扫描 143 | // mapc.put("input_type", 3); 144 | // //1--进 2--出 145 | // mapc.put("direction", 1); 146 | // mapc.put("test_type", 1); 147 | // map.put("content", mapc); 148 | 149 | Map map = new HashMap(); 150 | map.put("name",pass_number); 151 | map.put("age",sub_order_id); 152 | //旧httpclient请求方法,并发时封装不完善 153 | // //创建HxHttpClient对象 154 | // HxHttpClient hxHttpClient = HxHttpClient.getInstance(); 155 | // //传入请求的url、参数 156 | // hxHttpClient.config(url,"POST",map); 157 | // // 接收响应参数 158 | // HxHttpClientResponseData hxHttpClientResponseData = hxHttpClient.execute(); 159 | //并发时使用新的httpclient工具类ResponseEntity 160 | ResponseEntity responseEntity = RestTemplateUtils.post(url, map, Object.class); 161 | String str = JsonUtils.obj2json(responseEntity.getBody()); 162 | System.out.println("str:"+str); 163 | return str; 164 | } 165 | } -------------------------------------------------------------------------------- /src/test/java/testcase/RandomParameter.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import com.javaelf.utils.JsonUtils; 4 | import com.mifmif.common.regex.Generex; 5 | import org.apache.commons.lang3.RandomStringUtils; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.Random; 10 | import java.util.Set; 11 | 12 | public class RandomParameter { 13 | 14 | public static HashMap getStrParam(Integer leftBorder, Integer 15 | rightBorder, String paraName, String regular) { 16 | HashMap map = new HashMap(); 17 | ArrayList arrayList = new ArrayList(); 18 | Random random = new Random(); 19 | Generex generex = new Generex(regular); 20 | 21 | String empty = ""; 22 | String spaceStr = " "; 23 | String leftStr = RandomStringUtils.randomAlphanumeric(leftBorder); 24 | String middleStr = RandomStringUtils.randomAlphanumeric(random.nextInt(rightBorder - leftBorder + 1) + leftBorder); 25 | String rightStr = RandomStringUtils.randomAlphanumeric(rightBorder); 26 | String moreStr = RandomStringUtils.randomAlphanumeric(rightBorder + 1); 27 | String regStr = generex.random(); 28 | arrayList.add(empty); 29 | arrayList.add(spaceStr); 30 | arrayList.add(leftStr); 31 | arrayList.add(middleStr); 32 | arrayList.add(rightStr); 33 | arrayList.add(moreStr); 34 | arrayList.add(regStr); 35 | 36 | map.put(paraName, arrayList); 37 | map.put("middleStr", middleStr); 38 | return map; 39 | } 40 | 41 | public static HashMap getStrParam(Integer leftBorder, Integer 42 | rightBorder, String paraName) { 43 | HashMap map = new HashMap(); 44 | ArrayList arrayList = new ArrayList(); 45 | Random random = new Random(); 46 | 47 | String empty = ""; 48 | String spaceStr = " "; 49 | String lessStr = null; 50 | String leftStr = null; 51 | if (leftBorder > 0) { 52 | lessStr = RandomStringUtils.randomAlphanumeric(leftBorder - 1); 53 | } 54 | if (leftBorder != 0) { 55 | leftStr = RandomStringUtils.randomAlphanumeric(leftBorder); 56 | } 57 | String middleStr = RandomStringUtils.randomAlphanumeric(random.nextInt(rightBorder - leftBorder + 1) + leftBorder); 58 | String rightStr = RandomStringUtils.randomAlphanumeric(rightBorder); 59 | String moreStr = RandomStringUtils.randomAlphanumeric(rightBorder + 1); 60 | 61 | arrayList.add(empty); 62 | arrayList.add(spaceStr); 63 | if (lessStr != null) { 64 | arrayList.add(lessStr); 65 | } 66 | if (leftStr != null) { 67 | arrayList.add(leftStr); 68 | } 69 | arrayList.add(middleStr); 70 | arrayList.add(rightStr); 71 | arrayList.add(moreStr); 72 | 73 | map.put(paraName, arrayList); 74 | map.put("middleStr", middleStr); 75 | return map; 76 | } 77 | 78 | /** 79 | * 组合测试参数 80 | * 81 | * @param hashMaps 82 | * @return 83 | */ 84 | public static ArrayList> getOrgData(HashMap... hashMaps) { 85 | //变参参数名 86 | String paraName = null; 87 | //finalArrayList存放排列组合结果 88 | ArrayList> finalArrayList = new ArrayList(); 89 | //保存传参hashMaps,目的获取参数个数,hashMaps存放paraName和middleStr 90 | ArrayList> lengthArrayList = new ArrayList(); 91 | for (HashMap hashMap : hashMaps) { 92 | lengthArrayList.add(hashMap); 93 | } 94 | if(lengthArrayList.size()>1){ 95 | for (int i = 0; i < lengthArrayList.size(); i++) { 96 | // ArrayList> arrayList = new ArrayList(); 97 | //获取所有传参中的第i个值,定义为变参changehashMap 98 | HashMap changehashMap = lengthArrayList.get(i); 99 | //获取changehashMap需要测试参数名称 100 | Set keys = changehashMap.keySet(); 101 | for (String key : keys) { 102 | if (key != "middleStr") { 103 | paraName = key; 104 | } 105 | } 106 | //获取变参的changeArrayList,里面存放着需要测试的变化参数 107 | ArrayList changeArrayList = (ArrayList) changehashMap.get(paraName); 108 | //遍历变化参数,与middle(定值)组合 109 | for (int j = 0; j < changeArrayList.size(); j++) { 110 | HashMap orgHashMap = new HashMap(); 111 | //定值取lengthArrayList中hashMaps的middle值 112 | for (int k = 0; k < lengthArrayList.size(); k++) { 113 | //变参与自己不能组合 114 | if (i != k) { 115 | //获取定值的map 116 | HashMap otherHashMap = lengthArrayList.get(k); 117 | String otherParaName = null; 118 | //获取定值参数名 119 | Set otherkeys = otherHashMap.keySet(); 120 | for (String otherkey : otherkeys) { 121 | if (otherkey != "middleStr") { 122 | otherParaName = otherkey; 123 | } 124 | } 125 | //获取定值 126 | Object middleStr = otherHashMap.get("middleStr"); 127 | //变值与定值组合map 128 | orgHashMap.put(otherParaName, middleStr); 129 | String value = changeArrayList.get(j); 130 | orgHashMap.put(paraName, value); 131 | } 132 | } 133 | finalArrayList.add(orgHashMap); 134 | } 135 | } 136 | return finalArrayList; 137 | }else { 138 | HashMap changehashMap = lengthArrayList.get(0); 139 | Set keys = changehashMap.keySet(); 140 | for (String key : keys) { 141 | if (key != "middleStr") { 142 | paraName = key; 143 | } 144 | } 145 | //获取变参的changeArrayList,里面存放着需要测试的变化参数 146 | ArrayList changeArrayList = (ArrayList) changehashMap.get(paraName); 147 | for (int i = 0; i orgHashMap = new HashMap(); 149 | orgHashMap.put(paraName,changeArrayList.get(i)); 150 | finalArrayList.add(orgHashMap); 151 | } 152 | return finalArrayList; 153 | } 154 | } 155 | 156 | /** 157 | * 测试动态参数与静态参数结合 158 | * 159 | * @param hashMap 160 | * @return 161 | */ 162 | public static ArrayList requestBodyArrayList(ArrayList> finalArrayList, HashMap hashMap) { 163 | ArrayList arrayList = new ArrayList(); 164 | 165 | for (int i = 0; i objectHashMap = finalArrayList.get(i); 167 | objectHashMap.putAll(hashMap); 168 | String requestBody = JsonUtils.mapToJson(objectHashMap); 169 | arrayList.add(requestBody); 170 | } 171 | return arrayList; 172 | } 173 | 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/test/java/testcase/SpringBootTestCase.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import com.javaelf.JavaElfApplication; 4 | import com.javaelf.utils.CreateIDCardNo; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | @RunWith(SpringRunner.class) 12 | @SpringBootTest(classes = JavaElfApplication.class) 13 | public class SpringBootTestCase { 14 | 15 | public void getid(){ 16 | String createIDCardNo = CreateIDCardNo.getRandomID(); 17 | System.out.println(createIDCardNo); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/testcase/StreamStudy.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | 4 | import com.javaelf.entity.TestStreamEntity; 5 | import com.javaelf.utils.JsonUtils; 6 | import org.testng.annotations.Test; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.Comparator; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | import java.util.stream.Stream; 16 | 17 | /** 18 | * Stream流的操作练习 19 | * Stream(流)是一个来自数据源的元素队列并支持聚合操作 20 | * 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。 21 | * 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。 22 | * 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。 23 | *----------------------------------------------------------------------------- 24 | * 操作元素 25 | * (1)中间操作:流中间操作在应用到流上,返回一个新的流; 26 | * map:通过一个 Function 把一个元素类型为 T的流转换成元素类型为 R的流。 27 | * flatMap:扁平化流,通过一个 Function 把一个元素类型为 T 的流中的每个元素转换成一个元素类型为 R 的流,再把这些转换之后的流合并。 28 | * filter:过滤流中的元素,只保留满足由 Predicate 所指定的条件的元素。 29 | * distinct:筛选,通过流所生成元素的hashCode()和equals去除重复元素 30 | * limit:截断流使其最多只包含指定数量的元素。 31 | * skip:跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补 32 | * sorted:对流进行排序。 33 | * peek:返回的流与原始流相同。当原始流中的元素被消费时,会首先调用 peek 方法中指定的 Consumer 实现对元素进行处理。 34 | * dropWhile:从原始流起始位置开始删除满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。 35 | * takeWhile:从原始流起始位置开始保留满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。 36 | * …… 37 | * (2)终结操作:终结操作产生最终的结果; 38 | * forEach:遍历,自定义操作 39 | * allMatch:检查是否匹配所有元素 40 | * anyMatch:检查是否至少匹配一个元素 41 | * noneMatch:检查是否没有匹配所有元素 42 | * findFirst:返回第一个元素 43 | * findAny:返回当前流中的任意元素 44 | * count:返回流中元素的总个数 45 | * max:返回流中最大值 46 | * min:返回流中最小值 47 | * reduce:归约,递归操作,将流的每个元素反复结合形成得到新值 48 | * collect:收集,汇总操作(返回新集合、分组),接收一个Collector接口实现 49 | */ 50 | public class StreamStudy { 51 | /** 52 | * -Stream操作流,list+Array都可转换成流,操作方法雷同 53 | * 转换流方式: 54 | * (1)集合:list.stream() 55 | * (2)数组:Stream.of(arr) 或 Arrays.stream(strArray); 56 | * @author hqc 57 | * @date 2020年11月20日 58 | */ 59 | @Test 60 | public void tem() { 61 | /** 62 | * -初始化测试数据 63 | */ 64 | List> list = new ArrayList<>(); 65 | List listModel = new ArrayList<>(); 66 | 67 | //初始化map 68 | Map map1 = new HashMap<>(); 69 | map1.put("name", "孙悟空"); 70 | map1.put("age", 4); 71 | map1.put("sex", "女"); 72 | map1.put("grade", 89); 73 | Map map2 = new HashMap<>(); 74 | map2.put("name", "sixmonth"); 75 | map2.put("age", 3); 76 | map2.put("sex", "男"); 77 | map2.put("grade", 72); 78 | Map map3 = new HashMap<>(); 79 | map3.put("name", "sixmonth"); 80 | map3.put("age", 2); 81 | map3.put("sex", "女"); 82 | map3.put("grade", 66); 83 | list.add(map1); 84 | list.add(map2); 85 | list.add(map3); 86 | //初始化实体对象 87 | listModel.add(new TestStreamEntity("sixmonth", "男",23,99)); 88 | listModel.add(new TestStreamEntity("猪八戒", "男",678,56)); 89 | listModel.add(new TestStreamEntity("孙悟空", "男",567,88)); 90 | 91 | //初始化数组 92 | String[] arr = new String[] {"孙悟空","猪八戒","唐僧","唐僧"}; 93 | Integer[] arrInt = new Integer[] {88,45,23,78}; 94 | 95 | /** 96 | * -集合操作 97 | */ 98 | //listMap>filter:过滤,返回新集合 99 | List> resu = list.stream().filter(f -> f.get("sex").equals("女")).collect(Collectors.toList()); 100 | System.out.println("resu:"+ JsonUtils.obj2json(resu)); 101 | 102 | //listMap>map:修改对象值,返回新集合 103 | List resu1 = list.stream().map(ma->((String) ma.get("name")).split("")).collect(Collectors.toList()); 104 | System.out.println("resu1:"+JsonUtils.obj2json(resu1)); 105 | 106 | //listMap>flatMap:修改对象值,扁平化处理(即map操作的所有单个流,都会扁平化合并成一个流,映射成流的内容),返回新集合 107 | List resu2 = list.stream().map(ma->((String) ma.get("name")).split("")).flatMap(Arrays::stream).collect(Collectors.toList()); 108 | System.out.println("resu2:"+JsonUtils.obj2json(resu2)); 109 | 110 | //listMap>map:修改对象值,过滤重复对象值,返回新集合 111 | List resu3 = list.stream().map(ma->((String)ma.get("name"))).distinct().collect(Collectors.toList()); 112 | System.out.println("过滤重复值,resu3:"+JsonUtils.obj2json(resu3)); 113 | 114 | //listModel>map+forEach:修改对象值,遍历集合 115 | listModel.stream().map(TestStreamEntity::getName).forEach(System.out::println); 116 | 117 | //listModel>sort:根据分数排序,升序,返回新集合 118 | List resu5 = listModel.stream().sorted(Comparator.comparing(TestStreamEntity::getGrade)).collect(Collectors.toList()); 119 | System.out.println("根据分数排序,升序,返回新集合,resu5:"+JsonUtils.obj2json(resu5)); 120 | //listModel>sort:根据分数排序,倒序,返回新集合 121 | List resu6 = listModel.stream().sorted(Comparator.comparing(TestStreamEntity::getGrade).reversed()).collect(Collectors.toList()); 122 | System.out.println("根据分数排序,倒序,返回新集合,resu6:"+JsonUtils.obj2json(resu6)); 123 | //listMap>sort:根据分数排序,升序,返回新集合 124 | List> resu7 = list.stream().sorted((o1, o2) -> ((Integer) o1.get("grade")).compareTo((Integer)o2.get("grade"))).collect(Collectors.toList()); 125 | System.out.println("根据分数排序,升序,返回新集合,resu7:"+JsonUtils.obj2json(resu7)); 126 | 127 | //listModel>findFirst:查找符合条件的第一个元素,返回元素 128 | Map resu11= list.stream().filter(x -> x.get("sex").equals("女")).findFirst().orElseGet(null); 129 | System.err.println("查找符合条件的第一个元素,返回元素,resu11:"+(resu11==null?"null":resu11.get("name"))); 130 | 131 | //listModel>count:查找符合条件的元素,返回个数 132 | long resu12= list.stream().filter(x -> x.get("sex").equals("女")).count(); 133 | System.err.println("查找符合条件的元素,返回个数,resu12:"+resu12); 134 | 135 | //listModel>max:查找符合条件的最大元素,返回元素 136 | Integer maxGrade = listModel.stream().map(x->x.getGrade()).max(Integer::compareTo).orElse(0); 137 | System.err.println("查找符合条件的最大元素,返回元素,maxGrade:"+maxGrade); 138 | TestStreamEntity maxGradeModel = listModel.stream().max(Comparator.comparing(TestStreamEntity::getGrade)).orElse(null); 139 | System.err.println("查找符合条件的最大元素,返回元素,maxGradeModel:"+(maxGradeModel==null?"无":maxGradeModel.getName())); 140 | 141 | //listModel>min:查找符合条件的最小元素,返回元素 142 | Integer minGrade = listModel.stream().map(x->x.getGrade()).min(Integer::compareTo).orElse(0); 143 | System.err.println("查找符合条件的最小元素,返回元素,minGrade:"+minGrade); 144 | 145 | //listMap>max:查找符合条件的最大元素,返回元素 146 | Map maxGradeMap = list.stream().max((o1, o2) -> ((Integer) o1.get("grade")).compareTo((Integer)o2.get("grade"))).orElse(null); 147 | System.out.println("查找符合条件的最大元素,返回元素,maxGradeMap:"+(maxGradeMap==null?"无":maxGradeMap.get("name"))); 148 | 149 | //listMap>reduce:计算分数总数,返回总数 150 | // Integer gradeSum = list.stream().map(x -> (Integer)x.get("grade")).reduce(Integer::sum).orElse(0); 151 | Integer gradeSum = listModel.stream().map(TestStreamEntity::getGrade).reduce(Integer::sum).orElse(0); 152 | System.err.println("计算分数总和,返回总数,gradeSum:"+gradeSum); 153 | 154 | //listMap>collect>groupBy:分组统计,返回分组集合 155 | // Map>> sexMap = list.stream().collect(Collectors.groupingBy(x->x.get("sex"))); 156 | Map> sexMap = listModel.stream().collect(Collectors.groupingBy(TestStreamEntity::getSex)); 157 | System.err.println("根据性别分组,返回每种性别对应对象集合,sexMap:"+JsonUtils.obj2json(sexMap)); 158 | 159 | //listMap>collect>groupBy:分组统计,返回分组总分数 160 | // Map sexMapSum = list.stream().collect(Collectors.groupingBy(x->x.get("sex"),Collectors.summingInt (x->(Integer)x.get("grade")))); 161 | Map sexMapSum = listModel.stream().collect(Collectors.groupingBy(TestStreamEntity::getSex,Collectors.summingInt (TestStreamEntity::getGrade))); 162 | System.err.println("根据性别分组,返回分组总分数,sexMapSum:"+JsonUtils.obj2json(sexMapSum)); 163 | 164 | /** 165 | * -map操作 166 | */ 167 | //Map>forEach:遍历map 168 | map1.forEach((k,v)->System.out.println("遍历map:"+k+","+v)); 169 | 170 | //Map>forEach:流遍历map 171 | map1.entrySet().stream().forEach(x -> System.out.println("流遍历map:"+x.getValue())); 172 | 173 | /** 174 | * -数组操作 175 | */ 176 | //Array>forEach:遍历数组 177 | Stream.of(arr).forEach(System.out::println); 178 | 179 | //Array>distinct+forEach:过滤重复值,遍历集合 180 | Stream.of(arr).distinct().forEach(x ->{System.out.println("过滤重复值:"+x);}); 181 | 182 | //Array>limit+forEach:限制输出对象数量,遍历集合 183 | Stream.of(arr).limit(2).forEach(x ->{System.out.println("限制输出对象:"+x);}); 184 | 185 | //Array>limit+forEach:跳过n个对象数量,返回集合 186 | List resu4 = Stream.of(arr).skip(2).collect(Collectors.toList()); 187 | System.out.println("跳过n个对象,返回集合,resu4:"+JsonUtils.obj2json(resu4)); 188 | 189 | //Array>allMatch:是否匹配所有元素,返回boolean 190 | boolean resu8 = Stream.of(arr).allMatch(x -> x.equals("孙悟空")); 191 | System.out.println("是否匹配所有元素,返回boolean,resu8:"+resu8); 192 | 193 | //Array>anyMatch:是否存在元素,返回boolean 194 | boolean resu9 = Stream.of(arr).anyMatch(x -> x.equals("孙悟空")); 195 | System.out.println("是否匹配所有元素,返回boolean,resu9:"+resu9); 196 | 197 | //Array>noneMatch:是否不存在元素,返回boolean 198 | boolean resu10 = Stream.of(arr).noneMatch(x -> x.equals("白骨精")); 199 | System.out.println("是否匹配所有元素,返回boolean,resu10:"+resu10); 200 | 201 | //Array>reduce:是否不存在元素,返回boolean 202 | Integer sum = Stream.of(arrInt).reduce(0, Integer::sum); 203 | System.out.println("计算分数总和,返回总数,sum:"+sum); 204 | 205 | //Array>max:查找最大值,返回最大值 206 | Integer arrMax = Stream.of(arrInt).max(Integer::compareTo).orElse(0); 207 | System.out.println("查找最大值,返回最大值,arrMax:"+arrMax); 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /src/test/java/testcase/StreamStudyCase.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import com.javaelf.entity.TestStreamEntity; 4 | import com.javaelf.utils.JsonUtils; 5 | import org.testng.annotations.Test; 6 | 7 | import java.util.*; 8 | import java.util.stream.Collectors; 9 | 10 | import static java.util.stream.Collectors.*; 11 | 12 | public class StreamStudyCase { 13 | List listModel = new ArrayList<>(); 14 | //初始化数组 15 | String[] arr = new String[] {"孙悟空","猪八戒","唐僧","唐僧"}; 16 | Integer[] arrInt = new Integer[] {88,45,23,78}; 17 | String[] strList = new String[]{"test01","test002","test0003","test00004"}; 18 | 19 | List> list = new ArrayList<>(); 20 | /** 21 | * listMap ->filter 使用stream流的filter过滤,返回新的集合; 22 | * */ 23 | @Test 24 | public void streamCase1(){ 25 | Map map1 = new HashMap(); 26 | map1.put("sex","男"); 27 | map1.put("age",22); 28 | Map map2 = new HashMap(); 29 | map2.put("sex","女"); 30 | map2.put("age",20); 31 | list.add(map1); 32 | list.add(map2); 33 | List> listFilter = list.stream().filter(f -> f.get("sex").equals("女")) 34 | .collect(toList()); 35 | System.out.println(JsonUtils.obj2json(listFilter)); 36 | System.out.println(JsonUtils.obj2json(list)); 37 | } 38 | /** 39 | * listMap ->map 修改对象值返回新的集合(split)切割 40 | * 41 | * listMap>flatMap:修改对象值,扁平化处理(即map操作的所有单个流,都会扁平化合并成一个流,映射成流的内容),返回新集合 42 | * */ 43 | @Test 44 | public void streamCase2(){ 45 | Map map1 = new HashMap(); 46 | map1.put("sex","男"); 47 | map1.put("age",22); 48 | Map map2 = new HashMap(); 49 | map2.put("sex","女"); 50 | map2.put("age",20); 51 | list.add(map1); 52 | list.add(map2); 53 | List listMap = list.stream().map(m -> 54 | ((String)m.get("sex")).split("")).collect(Collectors.toList()); 55 | List listString = list.stream().map(ma-> 56 | ((String) ma.get("sex")).split("")).flatMap(Arrays::stream).collect(Collectors.toList()); 57 | System.out.println(JsonUtils.obj2json(list)); 58 | System.out.println(JsonUtils.obj2json(listMap)); 59 | System.out.println(listString); 60 | } 61 | /** 62 | * 过滤map的value参数值相同对象,返回值新的集合 63 | * */ 64 | @Test 65 | public void streamCase3(){ 66 | Map map1 = new HashMap(); 67 | map1.put("sex","男"); 68 | map1.put("age",22); 69 | Map map2 = new HashMap(); 70 | map2.put("sex","女"); 71 | map2.put("age",20); 72 | Map map3 = new HashMap(); 73 | map3.put("sex","女"); 74 | map3.put("age",20); 75 | list.add(map1); 76 | list.add(map2); 77 | list.add(map3); 78 | List listDistinct = list.stream().map(m -> 79 | ((String)m.get("sex"))).distinct().collect(Collectors.toList()); 80 | System.out.println(JsonUtils.obj2json(listDistinct)); 81 | } 82 | /** 83 | * 修改对象值,遍历集合 84 | * */ 85 | @Test 86 | public void streamCase4(){ 87 | Map resultMap = new HashMap<>(); 88 | List> listMap = new ArrayList<>(); 89 | //初始化实体对象 90 | listModel.add(new TestStreamEntity("sixmonth", "男",23,99)); 91 | listModel.add(new TestStreamEntity("猪八戒", "男",678,56)); 92 | listModel.add(new TestStreamEntity("孙悟空", "男",567,88)); 93 | // JDK8语法糖----类名::方法名 94 | listModel.stream().forEach( m ->{ 95 | String str = m.getSex().replace("男","女"); 96 | resultMap.put("sex",str); 97 | resultMap.put("name",m.name); 98 | resultMap.put("age",m.age); 99 | listMap.add(resultMap); 100 | }); 101 | System.out.println(JsonUtils.obj2json(listMap)); 102 | } 103 | //Lsit集合是可重复、有序存入取出 104 | @Test 105 | public void case5(){ 106 | List list = new ArrayList<>(); 107 | list.add("A"); 108 | list.add("B"); 109 | list.add("A"); 110 | System.out.println(list); 111 | } 112 | //Set集合,没有重复元素,存取无序 113 | @Test 114 | public void case6(){ 115 | int[] num = {2,5,7,5}; 116 | Set set = new HashSet<>(); 117 | for (int i =0 ; i map = new HashMap<>(); 137 | map.put("key1","value1"); 138 | map.put("key2","value2"); 139 | map.put("key3","value3"); 140 | for (String key : map.keySet()){ 141 | System.out.println(key+":"+map.get(key)); 142 | } 143 | } 144 | @Test 145 | public void mapFor1(){ 146 | //方法1:通过foreach循环遍历 147 | Map map = new HashMap<>(); 148 | map.put("key1","value1"); 149 | map.put("key2","value2"); 150 | map.put("key3","value3"); 151 | map.forEach((key,value) ->{ 152 | System.out.println(key + ":"+ value); 153 | }); 154 | } 155 | 156 | @Test 157 | public void mapFor2(){ 158 | //方法1:通过stream流遍历 159 | Map map = new HashMap<>(); 160 | map.put("key1","value1"); 161 | map.put("key2","value2"); 162 | map.put("key3","value3"); 163 | map.entrySet().stream().forEach((entry) ->{ 164 | System.out.println(entry.getKey() + ":" + entry.getValue()); 165 | }); 166 | } 167 | 168 | @Test 169 | public void arrayList(){ 170 | int a = 0; 171 | int length = 2; 172 | List list = new ArrayList<>(); 173 | List list1 = new ArrayList<>(length); 174 | List list2 = new ArrayList<>(); 175 | long start = System.currentTimeMillis(); 176 | for (int i = 0 ; i map = new HashMap<>(); 185 | map.put("key1","value1"); 186 | map.put("key2","value2"); 187 | map.put("key3","value3"); 188 | map.forEach((key,value)->{ 189 | System.out.println(key+value); 190 | }); 191 | list2.add(map); 192 | System.out.println(list2.toString()); 193 | } 194 | /** 195 | * 使用lambda 奥义一个接一个处理,直到业务处理完成 196 | * */ 197 | @Test 198 | public void lambadTest(){ 199 | List list = new ArrayList(Arrays.asList(strList)); 200 | list.stream().filter(s -> s.toString().length() > 7).forEach(System.out::println); 201 | } 202 | 203 | /** 204 | * 使用collector 重新生产一个新的list 205 | * */ 206 | @Test 207 | public void lambdaList(){ 208 | List list = new ArrayList(Arrays.asList(strList)); 209 | List list1 = (List) list.stream().filter(s -> s.toString().length() > 7).collect(Collectors.toList()); 210 | list1.forEach(System.out::println); 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/test/java/testcase/SumJavaLine.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.File; 7 | import java.io.FileReader; 8 | import java.io.IOException; 9 | /** 10 | * 面试被问到统计一个文件有效代码行数的实现 11 | * */ 12 | public class SumJavaLine { 13 | private static int i;//代码总行数 14 | private static int j;//文件个数 15 | 16 | @Test 17 | public static void Run() throws IOException { 18 | File file = new File("D:\\work\\java-elf\\src\\main\\java\\com\\javaelf\\controller");//需要统计行数的文件夹路径 19 | traverseFiles(file);//调用递归方法查看.java文件,用于统计行数 20 | System.out.println("所写文件个数:"+j); 21 | System.out.println("所写代码总行数:"+i); 22 | } 23 | public static void traverseFiles(File file) throws IOException{ 24 | if(!file.exists()){//文件不存在 25 | return; 26 | } 27 | 28 | if(!file.isDirectory()){//判断是否为文件 29 | String filename = file.getName(); 30 | if(filename.endsWith(".java")){//判断是否是.java文件 31 | j++; 32 | BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); 33 | String string =null; 34 | while ((string = bufferedReader.readLine()) != null) { 35 | i++;//读取行数 36 | } 37 | }else 38 | return; 39 | } 40 | 41 | File[] files =file.listFiles();//读取文件夹的子文件或子文件夹 42 | if (files == null || files.length == 0) { 43 | return; 44 | } 45 | 46 | for(File file2 : files){//如果是文件夹递归调用方法遍历文件 47 | traverseFiles(file2); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/testcase/Test.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | /** 9 | * @Author: 10 | * @Date: 11 | */ 12 | public class Test { 13 | 14 | @org.testng.annotations.Test 15 | public void test1() { 16 | HashMap otherPara = new HashMap(); 17 | otherPara.put("key1", "value1"); 18 | otherPara.put("key2", "value2"); 19 | otherPara.put("key3", "value3"); 20 | 21 | HashMap para1 = RandomParameter.getStrParam(7, 10, "para1"); 22 | 23 | HashMap para2 = RandomParameter.getStrParam(4, 6, "para2"); 24 | 25 | HashMap para3 = RandomParameter.getStrParam(0, 3, "para3"); 26 | 27 | HashMap para4 = RandomParameter.getStrParam(11, 21, "para4"); 28 | 29 | ArrayList> orgData = RandomParameter.getOrgData(para1, para2, para3, para4); 30 | System.out.println(orgData.size()); 31 | 32 | ArrayList strings = RandomParameter.requestBodyArrayList(orgData, otherPara); 33 | for (String str : strings) { 34 | System.out.println(str); 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/testcase/TestCaseDemo.java: -------------------------------------------------------------------------------- 1 | package testcase; 2 | 3 | import com.javaelf.utils.*; 4 | import org.apache.commons.lang.StringEscapeUtils; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.ResponseEntity; 7 | import org.testng.annotations.Test; 8 | 9 | import java.util.*; 10 | import java.util.stream.Collectors; 11 | 12 | public class TestCaseDemo { 13 | 14 | @Test 15 | public void case1(){ 16 | String str1 = "qzcsbj"; 17 | String str2 = "qzcsbj"; 18 | String str3 = new String("qzcsbj"); 19 | System.out.println(str1 == str2); 20 | System.out.println(str1 == str3); 21 | } 22 | 23 | @Test 24 | public void case3(){ 25 | String url = "http://192.168.1.57:811/platform-product/commodity/page-others"; 26 | String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMzIxNDAwMTQ5NjAzMzg5NDQwIiwiYXVkIjoiMDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjYiLCJjb21wYW55SWRzIjpbMTI2MDQ2MzA2NzEwODYxMDA0OF0sIm5iZiI6MTYwNDAyMTM3MSwiaXNzIjoicmVzdGFwaXVzZXIiLCJleHAiOjE2MDQwMjg1NzEsInVzZXJJZCI6MTMyMTQwMDE0OTYwMzM4OTQ0MCwiaWF0IjoxNjA0MDIxMzcxLCJqdGkiOiJiMzBmZjJjMi1kZTUxLTQ4ODYtYjNkMy01ODQ2YWIxOTc4NjkifQ.d73DENmtduK7M53HqVhIYb4Aq_1nOWAtvfBzOk3Wmzk"; 27 | HttpHeaders headers = new HttpHeaders(); 28 | headers.set("Authorization",token); 29 | ResponseEntity responseEntity = RestTemplateUtils.get(url,headers,Object.class,""); 30 | Map map = (Map) responseEntity.getBody(); 31 | System.out.println(JsonUtils.mapToJson(map)); 32 | } 33 | 34 | @Test 35 | public String case4(){ 36 | String str = "\ncom.javaelf.service.TestDataFactory\n"; 37 | String[] out = str.split("\n"); 38 | for (int i=0;i map = new HashMap<>(); 55 | map.put("corpid","ww27d6f876d80ceec6"); 56 | map.put("corpsecret","elaiRGcWe4JLESzypgnabA3Tvpj8kLiV6zLEqa4Nbw8"); 57 | String json = JsonUtils.obj2json(map); 58 | // String responseEntity = RestTemplateUtils.get(url,String.class,json).getBody(); 59 | String responseEntity = RestTemplateUtils.get(url,String.class,json).getBody(); 60 | System.out.println(responseEntity); 61 | } 62 | @Test 63 | public void case7(){ 64 | //字符串转map类型Map,再转 Map,放入 httpHeaders.setAll(mapStr); 65 | String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; 66 | String header = "{\"corpid\":\"${corpidTrue}\",\"corpsecret\":\"${corpidFalse}\"}"; 67 | Map map1 = JsonUtils.json2map(header); 68 | Map mapStr = new HashMap<>(); 69 | map1.keySet().stream().peek(mapKey -> { 70 | mapStr.put(mapKey, map1.get(mapKey).toString()); 71 | }).collect(Collectors.toList()); 72 | System.out.println(mapStr); 73 | HttpHeaders httpHeaders = new HttpHeaders(); 74 | httpHeaders.setAll(mapStr); 75 | String responseEntity = RestTemplateUtils.get(url,httpHeaders,String.class).getBody(); 76 | System.out.println(responseEntity); 77 | } 78 | 79 | /** 80 | * 二分查找,方法 81 | * */ 82 | @Test 83 | public int case8(int[] num,int startNum,int endNum,int findNum){ 84 | if (startNum <= endNum){ 85 | //算出中间位置 86 | int middle = (startNum+endNum)/2; 87 | //数组中间数字 88 | int middleValue = num[middle]; 89 | //二分查找 90 | if (findNum == middleValue){ 91 | return middle; 92 | }else if (findNum < middle){ 93 | //小于中间值,在中间值之前的数据中查找,使用递归 94 | return case8(num,startNum,middle-1,findNum); 95 | }else { 96 | //大于中间值在,在中间值之前查找 97 | return case8(num,middle+1,endNum,findNum); 98 | } 99 | } 100 | return -1; 101 | } 102 | 103 | @Test 104 | public void case9(){ 105 | //要查到的数组 106 | int[] binaryNums = new int[100]; 107 | //一次循环加入数据 108 | for (int i=0;i<100;i++){ 109 | binaryNums[i] =(i+1); 110 | } 111 | //定义要查找到的值 112 | int findNum = 65; 113 | int findResult = case8(binaryNums,0,binaryNums.length-1,findNum); 114 | System.out.println("元素的位置是:"+(findResult+1)); 115 | } 116 | @Test 117 | public void mandatory() { 118 | String json = "{\"yes\":{\"parames1\":\"11\",\"parames2\":\"22\",\"parames3\":\"33\",\"parames4\":\"44\"},\"no\":{\"parames8\":\"88\",\"parames9\":\"99\"}}"; 119 | Map map = JsonUtils.json2map(json); 120 | Map yesMap = (Map) map.get("yes"); 121 | Map noMap = (Map) map.get("no"); 122 | Set set = yesMap.keySet(); 123 | List> list = (List>) set.stream().map(m -> { 124 | Map hashMap = new HashMap<>(); 125 | //获取需要组合的必填项参数 126 | hashMap.put(m.toString(), yesMap.get(m)); 127 | return hashMap; 128 | }).collect(Collectors.toList()); 129 | Map objectMap = new HashMap<>(); 130 | Map valueMap = new HashMap<>(); 131 | for (int i = 0; i < list.size(); i++) { 132 | StringBuilder stringBuilder = new StringBuilder(); 133 | int finalI = i; 134 | list.stream().peek(mapParam -> { 135 | if (!list.get(finalI).equals(mapParam)) { 136 | stringBuilder.append(JsonUtils.mapToJson(mapParam)); 137 | } 138 | }).collect(Collectors.toList()); 139 | stringBuilder.append(JsonUtils.mapToJson(noMap)); 140 | objectMap.put("必填项" + list.get(i) + "为空的请求参数===>", stringBuilder.toString().replace("}{", ",")); 141 | } 142 | System.out.println(JsonUtils.mapToJson(objectMap)); 143 | } 144 | 145 | @Test 146 | public void mandatory22() { 147 | String json = "{\"yes\":{\"parames1\":\"11\",\"parames2\":\"22\",\"parames3\":\"33\",\"parames4\":\"44\",\"parames5\":\"55\"},\"no\":{\"parames8\":\"88\",\"parames9\":\"99\"}}"; 148 | String json2 = "{\"yes\": {\"parames1\": \"11\",\"parames2\": \"22\",\"parames3\": \"33\",\"parames4\": \"44\",\"parames5\": \"55\"},\"no\": {\"parames4\": \"88\",\"parames5\": \"99\"}}"; 149 | Map map = JsonUtils.json2map(json2); 150 | Map yesMap = (Map) map.get("yes"); 151 | Map noMap = (Map) map.get("no"); 152 | Set set = yesMap.keySet(); 153 | List> list = (List>) set.stream().map(m -> { 154 | Map hashMap = new HashMap<>(); 155 | //获取需要组合的必填项参数 156 | hashMap.put(m.toString(), yesMap.get(m)); 157 | return hashMap; 158 | }).collect(Collectors.toList()); 159 | Map objectMap = new HashMap<>(); 160 | for (int i = 0; i < list.size(); i++) { 161 | StringBuilder stringBuilder = new StringBuilder(); 162 | int finalI = i; 163 | list.stream().peek(mapParam -> { 164 | if (!list.get(finalI).equals(mapParam)) { 165 | stringBuilder.append(JsonUtils.mapToJson(mapParam)); 166 | } 167 | }).collect(Collectors.toList()); 168 | stringBuilder.append(JsonUtils.mapToJson(noMap)); 169 | objectMap.put("必填项" + list.get(i) + "为空的请求参数: ", stringBuilder.toString().replace("}{", ",")); 170 | } 171 | String str = JsonUtils.mapToJson(objectMap); 172 | str = StringEscapeUtils.unescapeJava(str); 173 | str=str.replace(" \":\"{"," \":{"); 174 | str=str.replace("}\",\"","},\""); 175 | str=str.replace("}\"}","}}"); 176 | System.out.println(str); 177 | } 178 | @Test 179 | public void mandatory1() { 180 | String json = "{\"parames1\": \"11\",\"parames2\": \"22\",\"parames3\": \"33\"}"; 181 | Map map = JsonUtils.json2map(json); 182 | Set set = map.keySet(); 183 | Map requestMap = new HashMap(); 184 | List> list = (List>) set.stream().map(m -> { 185 | Map hashMap = new HashMap<>(); 186 | //获取需要组合的必填项参数 187 | hashMap.put(m.toString(), map.get(m)); 188 | return hashMap; 189 | }).collect(Collectors.toList()); 190 | for (int i = 0; i < list.size(); i++) { 191 | int finalI = i; 192 | set.stream().forEach(k ->{ 193 | requestMap.put("参数值:"+k+"为空返回结果",map.get(k)); 194 | }); 195 | } 196 | String str = JsonUtils.mapToJson(requestMap); 197 | // str = StringEscapeUtils.unescapeJava(str); 198 | // str=str.replace(" \":\"{"," \":{"); 199 | // str=str.replace("}\",\"","},\""); 200 | // str=str.replace("}\"}","}}"); 201 | System.out.println(str); 202 | } 203 | 204 | @Test 205 | public void hybird(){ 206 | String json = "{\"parames1\": \"11\",\"parames2\": \"22\",\"parames3\": \"33\"}"; 207 | Map map = JsonUtils.json2map(json); 208 | TreeMap treeMap = new TreeMap(map); 209 | Set set = treeMap.keySet(); 210 | TreeMap treeMap1 = new TreeMap(); 211 | set.forEach(key ->{ 212 | Map reqMap = new HashMap(); 213 | treeMap.forEach((k,v)->{ 214 | if (key.equals(k)){ 215 | reqMap.put(k.toString(),""); 216 | }else { 217 | reqMap.put(k.toString(),v.toString()); 218 | } 219 | }); 220 | String format = String.format("参数值:%s为空返回结果", key); 221 | treeMap1.put(format,reqMap); 222 | }); 223 | System.out.println(JsonUtils.mapToJson(treeMap1)); 224 | } 225 | //测试随机数据的生成 226 | @Test 227 | public void getTestRandom(){ 228 | String str = RandomDataKit.randomDataStringInspect("测试-随机数Random(Long[3])"); 229 | System.out.println(str); 230 | } 231 | 232 | } 233 | --------------------------------------------------------------------------------