模拟用户管理系统java接口开发与测试实战

一.接口开发

1.引入依赖

 1 <parent>
 2     <groupId>org.springframework.boot</groupId>
 3     <artifactId>spring-boot-starter-parent</artifactId>
 4     <version>1.5.3.RELEASE</version>
 5   </parent>
 6 <dependency>
 7          <groupId>org.springframework.boot</groupId>
 8          <artifactId>spring-boot-starter-web</artifactId>
 9      </dependency>
10 
11      <dependency>
12          <groupId>io.springfox</groupId>
13          <artifactId>springfox-swagger-ui</artifactId>
14          <version>2.6.1</version>
15      </dependency>
16 
17      <dependency>
18          <groupId>io.springfox</groupId>
19          <artifactId>springfox-swagger2</artifactId>
20          <version>2.6.1</version>
21      </dependency>
22      
23      <dependency>
24          <groupId>org.projectlombok</groupId>
25          <artifactId>lombok</artifactId>
26          <version>1.16.14</version>
27      </dependency>
28      
29      <dependency>
30          <groupId>com.alibaba</groupId>
31          <artifactId>fastjson</artifactId>
32          <version>1.2.38</version>
33      </dependency>
34      <!-- 整合mybatis -->
35      <dependency>
36          <groupId>mysql</groupId>
37          <artifactId>mysql-connector-java</artifactId>
38      </dependency>
39      
40      <dependency>
41          <groupId>org.mybatis.spring.boot</groupId>
42          <artifactId>mybatis-spring-boot-starter</artifactId>
43          <version>1.3.0</version>
44      </dependency> 

2.application.yml文件配置

 1 server:
 2   port: 8888
 3 
 4 spring:
 5   application:
 6     name: userManager
 7   datasource:
 8     driver-class-name: com.mysql.jdbc.Driver
 9     url: jdbc:mysql://localhost:3306/test
10     username: root
11     password: admin3306
12 
13 mybatis:
14   type-aliases-package: com.test.pojo
15   mapper-locations:
16     - mapper/*

3.新建mapper包,包下新建SQLMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.test.pojo">
 6     <!-- 登录接口sql -->
 7     <select id="login" parameterType="com.test.pojo.User" resultType="Integer">
 8         select count(*) from user where username=#{username} and password=#{password};
 9     </select>
10     <!--添加用户接口  -->
11     <insert id="addUser" parameterType="com.test.pojo.User" >
12          insert into
13         user(username,password,sex,age,permisson,isDelete)
14         values
15         (#{username},#{password},#{sex},#{age},#{permisson},#{isDelete});
16     </insert>
17     <!-- 获取用户(列表)接口 -->
18     <!-- prefix:在trim标签内sql语句加上前缀
19     suffix:在trim标签内sql语句加上后缀
20     suffixOverrides:指定去除多余的后缀内容
21     prefixOverrides:指定去除多余的前缀内容 -->
22     <select id="getUserInfo" parameterType="com.test.pojo.User" resultType="com.test.pojo.User">
23         select * from user
24         <trim prefix="where" prefixOverrides="and">
25             <if test="null !=id and '' != id">
26                 AND id=#{id}
27             </if>
28             <if test="null !=username and '' != username">
29                 AND username=#{username}
30             </if>
31             <if test="null !=password and '' != password">
32                 AND password=#{password}
33             </if>
34             <if test="null !=age and '' != age">
35                 AND age=#{age}
36             </if>
37             <if test="null !=sex and '' != sex">
38                 AND sex=#{sex}
39             </if>
40             <if test="null !=permisson and '' != permisson">
41                 AND permisson=#{permisson}
42             </if>
43             <if test="null !=isDelete and '' != isDelete">
44                 AND isDelete=#{isDelete}
45             </if>
46         </trim>
47     </select>
48     
49     <!-- 更新删除用户接口 -->
50     <update id="updateUser">
51         update user 
52         <trim prefix="set" suffixOverrides=",">
53             <if test="null !=username and '' != username">
54                  username=#{username},
55             </if>
56             <if test="null !=password and '' != password">
57                  password=#{password},
58             </if>
59             <if test="null !=age and '' != age">
60                 age=#{age},
61             </if>
62             <if test="null !=sex and '' != sex">
63                 sex=#{sex},
64             </if>
65             <if test="null !=permisson and '' != permisson">
66                 permisson=#{permisson},
67             </if>
68             <if test="null !=isDelete and '' != isDelete">
69                 isDelete=#{isDelete},
70             </if>
71         </trim>
72         where id=#{id};
73     </update>
74 </mapper>

4.mybatis-config.xml文件配置

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 
 3 <!DOCTYPE configuration
 4             PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 5             "http://mybatis.org/dtd/mybatis-3-config.dtd">
 6 
 7 <configuration>
 8     <typeAliases>
 9         <package name="com.test.pojo"/>
10     </typeAliases>
11     <mappers>
12         <mapper resource="mapper/SQLMapper.xml"/>
13     </mappers>
14 </configuration>

5.logback配置

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <configuration
  3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4     xsi:noNamespaceSchemaLocation="http://www.padual.com/java/logback.xsd"
  5     debug="false" scan="true" scanPeriod="30 second">
  6 
  7     <property name="PROJECT" value="iorder" /> 
  8     <property name="ROOT" value="logs/${PROJECT}/" />
  9     <property name="FILESIZE" value="50MB" />
 10     <property name="MAXHISTORY" value="100" />
 11     <timestamp key="DATETIME" datePattern="yyyy-MM-dd HH:mm:ss" />
 12     <!-- 控制台打印 -->
 13     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 14         <encoder charset="utf-8">
 15             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
 16             </pattern>
 17         </encoder>
 18     </appender>
 19     <!-- ERROR 输入到文件,按日期和文件大小 -->
 20     <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 21         <encoder charset="utf-8">
 22             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
 23             </pattern>
 24         </encoder>
 25         <filter class="ch.qos.logback.classic.filter.LevelFilter">
 26             <level>ERROR</level>
 27             <onMatch>ACCEPT</onMatch>
 28             <onMismatch>DENY</onMismatch>
 29         </filter>
 30         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 31             <fileNamePattern>${ROOT}%d/error.%i.log</fileNamePattern>
 32             <maxHistory>${MAXHISTORY}</maxHistory>
 33             <timeBasedFileNamingAndTriggeringPolicy
 34                 class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 35                 <maxFileSize>${FILESIZE}</maxFileSize>
 36             </timeBasedFileNamingAndTriggeringPolicy>
 37         </rollingPolicy>
 38     </appender>
 39     
 40     <!-- WARN 输入到文件,按日期和文件大小 -->
 41     <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
 42         <encoder charset="utf-8">
 43             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
 44             </pattern>
 45         </encoder>
 46         <filter class="ch.qos.logback.classic.filter.LevelFilter">
 47             <level>WARN</level>
 48             <onMatch>ACCEPT</onMatch>
 49             <onMismatch>DENY</onMismatch>
 50         </filter>
 51         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 52             <fileNamePattern>${ROOT}%d/warn.%i.log</fileNamePattern>
 53             <maxHistory>${MAXHISTORY}</maxHistory>
 54             <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 55                 <maxFileSize>${FILESIZE}</maxFileSize>
 56             </timeBasedFileNamingAndTriggeringPolicy>
 57         </rollingPolicy>
 58     </appender>
 59     
 60     <!-- INFO 输入到文件,按日期和文件大小 -->
 61     <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
 62         <encoder charset="utf-8">
 63             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
 64             </pattern>
 65         </encoder>
 66         <filter class="ch.qos.logback.classic.filter.LevelFilter">
 67             <level>INFO</level>
 68             <onMatch>ACCEPT</onMatch>
 69             <onMismatch>DENY</onMismatch>
 70         </filter>
 71         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 72             <fileNamePattern>${ROOT}%d/info.%i.log</fileNamePattern>
 73             <maxHistory>${MAXHISTORY}</maxHistory>
 74             <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 75                 <maxFileSize>${FILESIZE}</maxFileSize>
 76             </timeBasedFileNamingAndTriggeringPolicy>
 77         </rollingPolicy>
 78     </appender>
 79     <!-- DEBUG 输入到文件,按日期和文件大小 -->
 80     <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
 81         <encoder charset="utf-8">
 82             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
 83             </pattern>
 84         </encoder>
 85         <filter class="ch.qos.logback.classic.filter.LevelFilter">
 86             <level>DEBUG</level>
 87             <onMatch>ACCEPT</onMatch>
 88             <onMismatch>DENY</onMismatch>
 89         </filter>
 90         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 91             <fileNamePattern>${ROOT}%d/debug.%i.log</fileNamePattern>
 92             <maxHistory>${MAXHISTORY}</maxHistory>
 93             <timeBasedFileNamingAndTriggeringPolicy
 94                 class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 95                 <maxFileSize>${FILESIZE}</maxFileSize>
 96             </timeBasedFileNamingAndTriggeringPolicy>
 97         </rollingPolicy>
 98     </appender>
 99     <!-- TRACE 输入到文件,按日期和文件大小 -->
100     <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
101         <encoder charset="utf-8">
102             <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
103             </pattern>
104         </encoder>
105         <filter class="ch.qos.logback.classic.filter.LevelFilter">
106             <level>TRACE</level>
107             <onMatch>ACCEPT</onMatch>
108             <onMismatch>DENY</onMismatch>
109         </filter>
110         <rollingPolicy
111             class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
112             <fileNamePattern>${ROOT}%d/trace.%i.log</fileNamePattern>
113             <maxHistory>${MAXHISTORY}</maxHistory>
114             <timeBasedFileNamingAndTriggeringPolicy
115                 class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
116                 <maxFileSize>${FILESIZE}</maxFileSize>
117             </timeBasedFileNamingAndTriggeringPolicy>
118         </rollingPolicy>
119     </appender>
120     
121     <!-- SQL相关日志输出-->
122     <logger name="org.apache.ibatis" level="INFO" additivity="false" />
123     <logger name="org.mybatis.spring" level="INFO" additivity="false" />
124     <logger name="com.github.miemiedev.mybatis.paginator" level="INFO" additivity="false" />
125     
126     <!-- Logger 根目录 -->
127     <root level="DEBUG">
128         <appender-ref ref="STDOUT" />
129         <appender-ref ref="DEBUG" />  
130         <appender-ref ref="ERROR" />
131         <appender-ref ref="WARN" />
132         <appender-ref ref="INFO" /> 
133         <appender-ref ref="TRACE" />
134     </root>
135 </configuration>

6.新建实体类User

 1 package com.test.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class User {
 7     private int id;
 8     private String username;
 9     private String password;
10     private int age;
11     private int sex;
12     private int permisson;
13     private int isDelete;
14 
15 }

7.新建SwaggerConfig

 1 package com.test.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import springfox.documentation.builders.ApiInfoBuilder;
 6 import springfox.documentation.builders.PathSelectors;
 7 import springfox.documentation.service.ApiInfo;
 8 import springfox.documentation.service.Contact;
 9 import springfox.documentation.spi.DocumentationType;
10 import springfox.documentation.spring.web.plugins.Docket;
11 import springfox.documentation.swagger2.annotations.EnableSwagger2;
12 
13 @Configuration
14 @EnableSwagger2
15 public class SwaggerConfig {
16     @Bean
17     public Docket api(){
18         return new Docket(DocumentationType.SWAGGER_2)
19                 .apiInfo(apiInfo())
20                 .pathMapping("/")
21                 .select()
22                 .paths(PathSelectors.regex("/.*"))
23                 .build();
24     }
25 
26     private ApiInfo apiInfo() {
27         return new ApiInfoBuilder().title("UserManager service API")
28                 .version("1.0")
29                 .build();
30     }
31 }

8.编写verifyCookies工具类

 1 package com.test.utils;
 2 
 3 import javax.servlet.http.Cookie;
 4 import javax.servlet.http.HttpServletRequest;
 5 
 6 import lombok.extern.log4j.Log4j;
 7 @Log4j
 8 public  class CookiesUtil {
 9     public static Boolean verifyCookies(HttpServletRequest request) {
10         Cookie[] cookie=request.getCookies();
11         if (cookie ==null) {
12             log.info("cookies为空");
13             return false;
14         }
15         for(Cookie c:cookie) {
16             if (c.getName().equals("login")&&c.getValue().equals("true")) {
17                  log.info("cookies验证通过");
18                     return true;
19             }
20         }
21         return false;
22     }
23 
24 }

9.新建controller,接口开发代码

 1 package com.test.controller;
 2 
 3 import java.util.List;
 4 
 5 import javax.servlet.http.Cookie;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import org.mybatis.spring.SqlSessionTemplate;
10 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.web.bind.annotation.PostMapping;
12 import org.springframework.web.bind.annotation.RequestBody;
13 import org.springframework.web.bind.annotation.RequestMapping;
14 import org.springframework.web.bind.annotation.RestController;
15 
16 import com.test.pojo.User;
17 import com.test.utils.CookiesUtil;
18 
19 import io.swagger.annotations.Api;
20 import io.swagger.annotations.ApiOperation;
21 import lombok.extern.log4j.Log4j;
22 @Log4j
23 @RestController
24 @Api(value = "/v1",description = "用户管理系统")
25 @RequestMapping("/v1")
26 public class UserMananger {
27     @Autowired
28     private SqlSessionTemplate template;
29     
30     @ApiOperation(value = "登录接口")
31     @PostMapping("/login")
32     public Boolean login(HttpServletResponse response,@RequestBody User user) {
33         int i=template.selectOne("login",user);
34         if (i==1) {
35             Cookie cookie= new Cookie("login", "true");
36             response.addCookie(cookie);
37             log.info("登录的用户是:"+user.getUsername());
38             return true;
39         }
40         return false;
41     }
42     
43     @ApiOperation(value = "添加用户接口")
44     @PostMapping("/addUser")
45     public Boolean addUser(HttpServletRequest request,@RequestBody User user) {
46         Boolean b=CookiesUtil.verifyCookies(request);
47         int i=0;
48         if (b) {
49             i= template.insert("addUser",user);
50         }
51         if (i>0) {
52             log.info("添加用户的数量是:"+i);
53             return true;
54         }
55         return false;
56     }
57     
58     @ApiOperation(value = "获取用户(列表)信息接口")
59     @PostMapping("/getUserInfo")
60     public List<User> getUserInfo(HttpServletRequest request,@RequestBody User user){
61         Boolean b =CookiesUtil.verifyCookies(request);
62         if (b) {
63             List<User> users =template.selectList("getUserInfo",user);
64             log.info("getUserInfo获取到的用户数量是"+users.size());
65             return users;
66         }
67         return null;
68     }
69     
70     @ApiOperation(value = "更新删除用户接口")
71     @PostMapping("/updateUser")
72     public int updateUser(HttpServletRequest request,@RequestBody User user) {
73         boolean b = CookiesUtil.verifyCookies(request);
74         int i=0;
75         if (b) {
76             i=template.update("updateUser",user);
77             
78         }
79         log.info("更新数据的条目数为:"+i);
80         return i;
81     }
82 
83 }

10.新建springboot启动类

package com.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

11.目录结构图

二.测试代码开发

1.新建一个maven工程,引入依赖

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3   <modelVersion>4.0.0</modelVersion>
 4     <parent>
 5         <groupId>org.springframework.boot</groupId>
 6         <artifactId>spring-boot-starter-parent</artifactId>
 7         <version>1.5.3.RELEASE</version>
 8     </parent>
 9   <groupId>com.test.autotest</groupId>
10   <artifactId>Charpter12</artifactId>
11   <version>0.0.1-SNAPSHOT</version>
12   <packaging>jar</packaging>
13 
14   <name>Charpter12</name>
15   <url>http://maven.apache.org</url>
16 
17   <properties>
18     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19   </properties>
20 
21   <dependencies>
22     <dependency>
23         <groupId>org.apache.httpcomponents</groupId>
24         <artifactId>httpclient</artifactId>
25         <version>4.1.2</version>
26     </dependency>
27     <dependency>
28         <groupId>org.json</groupId>
29         <artifactId>json</artifactId>
30         <version>20170516</version>
31     </dependency>
32     <dependency>
33         <groupId>org.mybatis.spring.boot</groupId>
34         <artifactId>mybatis-spring-boot-starter</artifactId>
35         <version>1.3.0</version>
36     </dependency>
37     <dependency>
38         <groupId>org.mybatis</groupId>
39         <artifactId>mybatis</artifactId>
40         <version>3.4.4</version>
41     </dependency>
42     <dependency>
43         <groupId>mysql</groupId>
44         <artifactId>mysql-connector-java</artifactId>
45         <version>5.1.6</version>
46     </dependency>
47     <dependency>
48         <groupId>org.projectlombok</groupId>
49         <artifactId>lombok</artifactId>
50         <version>1.16.14</version>
51     </dependency>
52 
53     <dependency>
54         <groupId>com.relevantcodes</groupId>
55         <artifactId>extentreports</artifactId>
56         <version>2.41.1</version>
57     </dependency>
58     <dependency>
59         <groupId>com.vimalselvam</groupId>
60         <artifactId>testng-extentsreport</artifactId>
61         <version>1.3.1</version>
62     </dependency>
63     <dependency>
64         <groupId>com.aventstack</groupId>
65         <artifactId>extentreports</artifactId>
66         <version>3.0.6</version>
67     </dependency>
68 
69     <dependency>
70         <groupId>org.testng</groupId>
71         <artifactId>testng</artifactId>
72         <version>6.10</version>
73     </dependency>
74     <dependency>
75         <groupId>commons-logging</groupId>
76         <artifactId>commons-logging</artifactId>
77         <version>1.2</version>
78     </dependency> 
79     <dependency>
80         <groupId>org.springframework.boot</groupId>
81         <artifactId>spring-boot-starter-web</artifactId>
82         <version>1.5.3.RELEASE</version>
83     </dependency>
84     <dependency>
85         <groupId>io.springfox</groupId>
86         <artifactId>springfox-swagger2</artifactId>
87         <version>2.6.1</version>
88     </dependency>
89     <dependency>
90         <groupId>io.springfox</groupId>
91         <artifactId>springfox-swagger-ui</artifactId>
92         <version>2.6.1</version>
93     </dependency>
94   </dependencies>
95 </project>

2.application.properties配置

 1 test.url=http://localhost:8888
 2 
 3 #登陆接口
 4 login.uri=/v1/login
 5 
 6 #更新用户信息接口
 7 updateUserInfo.uri=/v1/updateUserInfo
 8 
 9 #获取用户列表接口
10 getUserList.uri=/v1/getUserInfo
11 
12 #获取用户信息接口
13 getUserInfo.uri=/v1/getUserInfo
14 
15 #添加用户接口
16 addUser.uri=/v1/addUser

3.mybatis.xml配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 3         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 4 
 5 <configuration>
 6     <!-- 注册对象的空间命名 -->
 7     <environments default="development">
 8         <environment id="development">
 9             <transactionManager type="JDBC"/>
10             <dataSource type="POOLED">
11                 <!-- 1.加载数据库驱动 -->
12                 <property name="driver" value="com.mysql.jdbc.Driver"/>
13                 <!-- 2.数据库连接地址 -->
14                 <property name="url" value="jdbc:mysql://localhost:3306/test"/>
15                 <!-- 数据库用户... -->
16                 <property name="username" value="root"/>
17                 <!-- 数据库密码... -->
18                 <property name="password" value="admin3306"/>
19             </dataSource>
20         </environment>
21     </environments>
22     <!-- 注册映射文件:java对象与数据库之间的xml文件路径! -->
23     <mappers>
24         <mapper resource="mapper/SQLMapper.xml"/>
25     </mappers>
26 </configuration>

4.新建mapper包,包下新建SQLMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 3         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 4 
 5 <mapper namespace="com.test.pojo">
 6     <!--获取登陆接口case-->
 7     <select id="loginCase" parameterType="Integer" resultType="com.test.pojo.LoginCase">
 8         select * from loginCase
 9         where id=#{id};
10     </select>
11     
12     <!--添加用户接口case  -->
13     <select id="addUserCase" parameterType="Integer" resultType="com.test.pojo.AddUserCase">
14         select * from addusercase where id =#{id};
15     </select>
16     
17     <!-- 查询添加用户接口 -->
18     <select id="addUser" parameterType="com.test.pojo.AddUserCase" resultType="com.test.pojo.User">
19         select * from user where
20         username = #{username}
21         and password=#{password}
22         and sex=#{sex}
23         and age=#{age}
24         and permisson=#{permisson}
25         and isDelete=#{isDelete};
26     </select>
27     
28     <!-- 查询用户信息接口case  -->
29     <select id="getUserInfoCase"  parameterType="Integer" resultType="com.test.pojo.GetUserInfoCase">
30         select * from getuserinfocase where id=#{id};
31     </select>
32     
33     <!--查询获取用户信息接口-->
34     <select id="getUserInfo" parameterType="com.test.cases.GetUserInfoTest" resultType="com.test.pojo.User">
35         select * from user where
36         id=#{userid};
37     </select>
38     
39     <!-- 获取用户信息列表接口case -->
40     <select id="getUserInfoListCase" parameterType="Integer" resultType="com.test.pojo.GetUserListCase">
41         select * from getuserlistcase where id=#{id};
42     </select>
43     
44     <!-- 获取用户信息列表接口 -->
45      <select id="getUserInfoList" parameterType="com.test.pojo.GetUserListCase" resultType="com.test.pojo.User">
46         select * from user 
47          <trim prefix="WHERE" prefixOverrides="and">
48             <if test="null !=username and ''!=username">
49                 AND username=#{username}
50             </if>
51             <if test="null !=sex and ''!=sex">
52                 AND sex=#{sex}
53             </if>
54             <if test="null !=age and ''!=age">
55                 AND age=#{age}
56             </if>
57         </trim>
58         ;
59     </select>
60     
61     <!-- 修改/删除用户信息case -->
62     <select id="updateUserInfoCase" parameterType="Integer" resultType="com.test.pojo.UpdateUserInfoCase">
63         select * from updateuserinfocase where id=#{id};
64     </select>
65     
66     <!--获取修改后用户信息  -->
67     <select id="getUpdateUserInfo" parameterType="com.test.pojo.UpdateUserInfoCase" resultType="com.test.pojo.User">
68         select * from user
69         <trim prefix="WHERE" prefixOverrides="and">
70             <if test="null !=username and ''!=username">
71                 AND username=#{username}
72             </if>
73             <if test="null !=sex and ''!=sex">
74                 AND sex=#{sex}
75             </if>
76             <if test="null !=age and ''!=age">
77                 AND age=#{age}
78             </if>
79             <if test="null !=permisson and ''!=permisson">
80                 AND permisson=#{permisson}
81             </if>
82             <if test="null !=isDelete and ''!=isDelete">
83                 AND isDelete=#{isDelete}
84             </if>
85         </trim>
86         And id = #{userid}
87     </select>
88 </mapper>

5.logback配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.padual.com/java/logback.xsd"
    debug="false" scan="true" scanPeriod="30 second">

    <property name="PROJECT" value="iorder" /> 
    <property name="ROOT" value="logs/${PROJECT}/" />
    <property name="FILESIZE" value="50MB" />
    <property name="MAXHISTORY" value="100" />
    <timestamp key="DATETIME" datePattern="yyyy-MM-dd HH:mm:ss" />
    <!-- 控制台打印 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
    </appender>
    <!-- ERROR 输入到文件,按日期和文件大小 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/error.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- WARN 输入到文件,按日期和文件大小 -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/warn.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- INFO 输入到文件,按日期和文件大小 -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/info.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <!-- DEBUG 输入到文件,按日期和文件大小 -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/debug.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <!-- TRACE 输入到文件,按日期和文件大小 -->
    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder charset="utf-8">
            <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>TRACE</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${ROOT}%d/trace.%i.log</fileNamePattern>
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
    <!-- SQL相关日志输出-->
    <logger name="org.apache.ibatis" level="INFO" additivity="false" />
    <logger name="org.mybatis.spring" level="INFO" additivity="false" />
    <logger name="com.github.miemiedev.mybatis.paginator" level="INFO" additivity="false" />
    
    <!-- Logger 根目录 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="DEBUG" />  
        <appender-ref ref="ERROR" />
        <appender-ref ref="WARN" />
        <appender-ref ref="INFO" /> 
        <appender-ref ref="TRACE" />
    </root>
</configuration>

6.与数据库对应的实体类

 1 package com.test.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class AddUserCase {
 7     private String username;
 8     private String password;
 9     private int sex;
10     private int age;
11     private int permisson;
12     private int isDelete;
13     private String expected;
14 }
 1 package com.test.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class GetUserInfoCase {
 7 
 8     private int userid;
 9     private String expected;
10 }
 1 package com.test.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class GetUserListCase {
 7     private String username;
 8     private int age;
 9     private int sex;
10     private String expected;
11 
12 }
1 package com.test.pojo;
2 
3 public enum InterfaceName {
4     GETUSERLIST,LOGIN,UPDATEUSERINFO,GETUSERINFO,ADDUSERINFO
5 }
 1 package com.test.pojo;
 2 
 3 import lombok.Data;
 4 
 5 @Data
 6 public class LoginCase {
 7     private int id;
 8     private String username;
 9     private String password;
10     private String expected;
11 
12 }
 1 package com.test.pojo;
 2 
 3 
 4 import lombok.Data;
 5 
 6 @Data
 7 public class UpdateUserInfoCase {
 8     private int id;
 9     private int userid;
10     private String username;
11     private int sex;
12     private int age;
13     private int permisson;
14     private int isDelete;
15     private String expected;
16 }
package com.test.pojo;

import lombok.Data;

@Data
public class User {

    private int id;
    private String username;
    private String password;
    private int age;
    private int sex;
    private int permisson;
    private int isDelete;

    @Override
    public String toString(){
        return(
           "{id:"+id+","+
           "userName:"+username+","+
           "password:"+password+","+
           "age:"+age+","+
           "sex:"+sex+","+
           "permission:"+permisson+","+
           "isDelete:"+isDelete+"}"
                );
    }

}

7.工具类设计

 1 package com.test.utils;
 2 
 3 import java.util.Locale;
 4 import java.util.ResourceBundle;
 5 
 6 import com.test.pojo.InterfaceName;
 7 
 8 public class ConfigFile {
 9 
10     private static ResourceBundle bundle = ResourceBundle.getBundle("application", Locale.CHINA);
11 
12     public static String getUrl(InterfaceName name){
13         String address = bundle.getString("test.url");
14         String uri="";
15         //最终的测试地址
16         String testUrl;
17 
18         if(name == InterfaceName.GETUSERLIST){
19             uri = bundle.getString("getUserList.uri");
20         }
21 
22         if(name == InterfaceName.LOGIN){
23             uri = bundle.getString("login.uri");
24         }
25 
26         if(name == InterfaceName.UPDATEUSERINFO){
27             uri = bundle.getString("updateUserInfo.uri");
28         }
29 
30         if(name == InterfaceName.GETUSERINFO){
31             uri = bundle.getString("getUserInfo.uri");
32         }
33 
34         if(name == InterfaceName.ADDUSERINFO){
35             uri = bundle.getString("addUser.uri");
36         }
37 
38         testUrl = address + uri;
39         return testUrl;
40     }
41 
42 }
 1 package com.test.utils;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.Reader;
10 
11 public class DatabaseUtil {
12 
13     public static SqlSession getSqlSession() throws IOException {
14         //获取配置的资源文件
15         Reader reader = Resources.getResourceAsReader("mybatis.xml");
16 
17         SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
18         //sqlSession就是能够执行配置文件中的sql语句。
19         SqlSession sqlSession = factory.openSession();
20 
21         return sqlSession;
22     }
23 
24 }

8.配置类设计

 1 package com.test.config;
 2 
 3 import org.apache.http.client.CookieStore;
 4 import org.apache.http.impl.client.DefaultHttpClient;
 5 
 6 public class TestConfig {
 7     public static String loginUrl;
 8     public static String updateUserInfoUrl;
 9     public static String getUserListUrl;
10     public static String getUserInfoUrl;
11     public static String addUserUrl;
12 
13 
14     public static DefaultHttpClient defaultHttpClient;
15     public static CookieStore store;
16 
17 }
  1 package com.test.config;
  2 
  3 
  4 import com.aventstack.extentreports.ExtentReports;
  5 import com.aventstack.extentreports.ExtentTest;
  6 import com.aventstack.extentreports.ResourceCDN;
  7 import com.aventstack.extentreports.Status;
  8 import com.aventstack.extentreports.model.TestAttribute;
  9 import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
 10 import com.aventstack.extentreports.reporter.configuration.ChartLocation;
 11 import com.aventstack.extentreports.reporter.configuration.Theme;
 12 import org.testng.*;
 13 import org.testng.xml.XmlSuite;
 14 
 15 import java.io.File;
 16 import java.util.*;
 17 
 18 public class ExtentTestNGIReporterListener implements IReporter {
 19     //生成的路径以及文件名
 20     private static final String OUTPUT_FOLDER = "test-output/";
 21     private static final String FILE_NAME = "extend_report.html";
 22 
 23     private ExtentReports extent;
 24 
 25     @Override
 26     public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
 27         init();
 28         boolean createSuiteNode = false;
 29         if(suites.size()>1){
 30             createSuiteNode=true;
 31         }
 32         for (ISuite suite : suites) {
 33             Map<String, ISuiteResult> result = suite.getResults();
 34             //如果suite里面没有任何用例,直接跳过,不在报告里生成
 35             if(result.size()==0){
 36                 continue;
 37             }
 38             //统计suite下的成功、失败、跳过的总用例数
 39             int suiteFailSize=0;
 40             int suitePassSize=0;
 41             int suiteSkipSize=0;
 42             ExtentTest suiteTest=null;
 43             //存在多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。
 44             if(createSuiteNode){
 45                 suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
 46             }
 47             boolean createSuiteResultNode = false;
 48             if(result.size()>1){
 49                 createSuiteResultNode=true;
 50             }
 51             for (ISuiteResult r : result.values()) {
 52                 ExtentTest resultNode;
 53                 ITestContext context = r.getTestContext();
 54                 if(createSuiteResultNode){
 55                     //没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点。
 56                     if( null == suiteTest){
 57                         resultNode = extent.createTest(r.getTestContext().getName());
 58                     }else{
 59                         resultNode = suiteTest.createNode(r.getTestContext().getName());
 60                     }
 61                 }else{
 62                     resultNode = suiteTest;
 63                 }
 64                 if(resultNode != null){
 65                     resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());
 66                     if(resultNode.getModel().hasCategory()){
 67                         resultNode.assignCategory(r.getTestContext().getName());
 68                     }else{
 69                         resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
 70                     }
 71                     resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
 72                     resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
 73                     //统计SuiteResult下的数据
 74                     int passSize = r.getTestContext().getPassedTests().size();
 75                     int failSize = r.getTestContext().getFailedTests().size();
 76                     int skipSize = r.getTestContext().getSkippedTests().size();
 77                     suitePassSize += passSize;
 78                     suiteFailSize += failSize;
 79                     suiteSkipSize += skipSize;
 80                     if(failSize>0){
 81                         resultNode.getModel().setStatus(Status.FAIL);
 82                     }
 83                     resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
 84                 }
 85                 buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
 86                 buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
 87                 buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
 88             }
 89             if(suiteTest!= null){
 90                 suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
 91                 if(suiteFailSize>0){
 92                     suiteTest.getModel().setStatus(Status.FAIL);
 93                 }
 94             }
 95 
 96         }
 97 //        for (String s : Reporter.getOutput()) {
 98 //            extent.setTestRunnerOutput(s);
 99 //        }
100 
101         extent.flush();
102     }
103 
104     private void init() {
105         //文件夹不存在的话进行创建
106         File reportDir= new File(OUTPUT_FOLDER);
107         if(!reportDir.exists()&& !reportDir .isDirectory()){
108             reportDir.mkdir();
109         }
110         ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
111         // 设置静态文件的DNS
112         //怎么样解决cdn.rawgit.com访问不了的情况
113         htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);
114 
115         htmlReporter.config().setDocumentTitle("api自动化测试报告");
116         htmlReporter.config().setReportName("api自动化测试报告");
117         htmlReporter.config().setChartVisibilityOnOpen(true);
118         htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
119         htmlReporter.config().setTheme(Theme.STANDARD);
120         htmlReporter.config().setCSS(".node.level-1  ul{ display:none;} .node.level-1.active ul{display:block;}");
121         extent = new ExtentReports();
122         extent.attachReporter(htmlReporter);
123         extent.setReportUsesManualConfiguration(true);
124     }
125 
126     private void buildTestNodes(ExtentTest extenttest, IResultMap tests, Status status) {
127         //存在父节点时,获取父节点的标签
128         String[] categories=new String[0];
129         if(extenttest != null ){
130             List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();
131             categories = new String[categoryList.size()];
132             for(int index=0;index<categoryList.size();index++){
133                 categories[index] = categoryList.get(index).getName();
134             }
135         }
136 
137         ExtentTest test;
138 
139         if (tests.size() > 0) {
140             //调整用例排序,按时间排序
141             Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {
142                 @Override
143                 public int compare(ITestResult o1, ITestResult o2) {
144                     return o1.getStartMillis()<o2.getStartMillis()?-1:1;
145                 }
146             });
147             treeSet.addAll(tests.getAllResults());
148             for (ITestResult result : treeSet) {
149                 Object[] parameters = result.getParameters();
150                 String name="";
151                 //如果有参数,则使用参数的toString组合代替报告中的name
152                 for(Object param:parameters){
153                     name+=param.toString();
154                 }
155                 if(name.length()>0){
156                     if(name.length()>50){
157                         name= name.substring(0,49)+"...";
158                     }
159                 }else{
160                     name = result.getMethod().getMethodName();
161                 }
162                 if(extenttest==null){
163                     test = extent.createTest(name);
164                 }else{
165                     //作为子节点进行创建时,设置同父节点的标签一致,便于报告检索。
166                     test = extenttest.createNode(name).assignCategory(categories);
167                 }
168                 //test.getModel().setDescription(description.toString());
169                 //test = extent.createTest(result.getMethod().getMethodName());
170                 for (String group : result.getMethod().getGroups())
171                     test.assignCategory(group);
172 
173                 List<String> outputList = Reporter.getOutput(result);
174                 for(String output:outputList){
175                     //将用例的log输出报告中
176                     test.debug(output);
177                 }
178                 if (result.getThrowable() != null) {
179                     test.log(status, result.getThrowable());
180                 }
181                 else {
182                     test.log(status, "Test " + status.toString().toLowerCase() + "ed");
183                 }
184 
185                 test.getModel().setStartTime(getTime(result.getStartMillis()));
186                 test.getModel().setEndTime(getTime(result.getEndMillis()));
187             }
188         }
189     }
190 
191     private Date getTime(long millis) {
192         Calendar calendar = Calendar.getInstance();
193         calendar.setTimeInMillis(millis);
194         return calendar.getTime();
195     }
196 }

9.测试代码设计

 1 package com.test.cases;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.http.HttpResponse;
 6 import org.apache.http.client.methods.HttpPost;
 7 import org.apache.http.entity.StringEntity;
 8 import org.apache.http.impl.client.DefaultHttpClient;
 9 import org.apache.http.util.EntityUtils;
10 import org.apache.ibatis.session.SqlSession;
11 import org.json.JSONObject;
12 import org.testng.Assert;
13 import org.testng.annotations.BeforeTest;
14 import org.testng.annotations.Test;
15 
16 import com.test.config.TestConfig;
17 import com.test.pojo.InterfaceName;
18 import com.test.pojo.LoginCase;
19 import com.test.utils.ConfigFile;
20 import com.test.utils.DatabaseUtil;
21 
22 public class LoginTest {
23 
24     @BeforeTest(groups = "loginTrue",description = "测试准备工作,获取HttpClient对象")
25     public void beforeTest(){
26         TestConfig.getUserInfoUrl = ConfigFile.getUrl(InterfaceName.GETUSERINFO);
27         TestConfig.getUserListUrl = ConfigFile.getUrl(InterfaceName.GETUSERLIST);
28         TestConfig.addUserUrl = ConfigFile.getUrl(InterfaceName.ADDUSERINFO);
29         TestConfig.loginUrl = ConfigFile.getUrl(InterfaceName.LOGIN);
30         TestConfig.updateUserInfoUrl = ConfigFile.getUrl(InterfaceName.UPDATEUSERINFO);
31         TestConfig.defaultHttpClient = new DefaultHttpClient();
32     }
33 
34     @Test(groups = "loginTrue",description = "用户登陆成功接口测试")
35     public void loginTrue() throws IOException {
36         SqlSession session = DatabaseUtil.getSqlSession();
37         LoginCase loginCase = session.selectOne("loginCase",1);
38         //发送请求
39         String result = getResult(loginCase);
40         //验证结果
41         Assert.assertEquals(loginCase.getExpected(),result);
42 
43     }
44     @Test(groups = "loginFalse",description = "用户登陆失败接口测试")
45     public void loginFalse() throws IOException {
46         SqlSession session = DatabaseUtil.getSqlSession();
47         LoginCase loginCase = session.selectOne("loginCase",2);
48         //发送请求
49         String result = getResult(loginCase);
50         //验证结果
51         Assert.assertEquals(loginCase.getExpected(),result);
52 
53     }
54 
55 
56 
57     private String getResult(LoginCase loginCase) throws IOException {
58         HttpPost post = new HttpPost(TestConfig.loginUrl);
59         JSONObject param = new JSONObject();
60         param.put("username",loginCase.getUsername());
61         param.put("password",loginCase.getPassword());
62         post.setHeader("content-type","application/json");
63         StringEntity entity = new StringEntity(param.toString(),"utf-8");
64         post.setEntity(entity);
65         String result;
66         HttpResponse response = TestConfig.defaultHttpClient.execute(post);
67         result = EntityUtils.toString(response.getEntity(),"utf-8");
68         TestConfig.store = TestConfig.defaultHttpClient.getCookieStore();
69         return  result;
70     }
71 }
 1 package com.test.cases;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.http.HttpResponse;
 6 import org.apache.http.client.ClientProtocolException;
 7 import org.apache.http.client.methods.HttpPost;
 8 import org.apache.http.entity.StringEntity;
 9 import org.apache.http.util.EntityUtils;
10 import org.apache.ibatis.session.SqlSession;
11 import org.json.JSONObject;
12 import org.testng.Assert;
13 import org.testng.annotations.Test;
14 
15 import com.test.config.TestConfig;
16 import com.test.pojo.AddUserCase;
17 import com.test.pojo.User;
18 import com.test.utils.DatabaseUtil;
19 
20 public class AddUserTest {
21     
22     @Test(dependsOnGroups = "loginTrue",description = "添加用户接口测试")
23     public void addUser() throws IOException, InterruptedException {
24         SqlSession session = DatabaseUtil.getSqlSession();
25         AddUserCase addUserCase = session.selectOne("addUserCase",2);
26         //发送请求
27         String result = getResult(addUserCase);
28 //        Thread.sleep(5000); 
29 //        User user = session.selectOne("addUser",addUserCase);
30 //        System.out.println(user.toString());
31         //验证结果
32         Assert.assertEquals(addUserCase.getExpected(),result);
33     }
34 
35     private String getResult(AddUserCase addUserCase) throws ClientProtocolException, IOException {
36         HttpPost post = new HttpPost(TestConfig.addUserUrl);
37         JSONObject param = new JSONObject();
38         param.put("username",addUserCase.getUsername());
39         param.put("password",addUserCase.getPassword());
40         param.put("age",addUserCase.getAge());
41         param.put("sex",addUserCase.getSex());
42         param.put("permisson",addUserCase.getPermisson());
43         param.put("isDelete",addUserCase.getIsDelete());
44         post.setHeader("content-type","application/json");
45         StringEntity entity = new StringEntity(param.toString(),"utf-8");
46         post.setEntity(entity);
47         //设置cookies
48         TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
49         String result;
50         HttpResponse response = TestConfig.defaultHttpClient.execute(post);
51         result = EntityUtils.toString(response.getEntity(),"utf-8");
52         return  result;
53     }
54 }
 1 package com.test.cases;
 2 
 3 import java.io.IOException;
 4 import java.util.Arrays;
 5 import java.util.List;
 6 
 7 import org.apache.http.HttpResponse;
 8 import org.apache.http.client.ClientProtocolException;
 9 import org.apache.http.client.methods.HttpPost;
10 import org.apache.http.entity.StringEntity;
11 import org.apache.http.util.EntityUtils;
12 import org.apache.ibatis.session.SqlSession;
13 import org.json.JSONArray;
14 import org.json.JSONObject;
15 import org.testng.Assert;
16 import org.testng.annotations.Test;
17 
18 import com.test.config.TestConfig;
19 import com.test.pojo.GetUserInfoCase;
20 import com.test.pojo.GetUserListCase;
21 import com.test.pojo.User;
22 import com.test.utils.DatabaseUtil;
23 
24 public class GetUserInfoListTest {
25     @Test(dependsOnGroups = "loginTrue",description = "获取sex为0的用户信息")
26     public void getUserInfoList() throws IOException {
27         SqlSession session = DatabaseUtil.getSqlSession();
28         GetUserListCase getUserListCase = session.selectOne("getUserInfoListCase",1);
29         JSONArray resultJson=getJsonResult(getUserListCase);
30         System.out.println(resultJson.toString());
31         //验证
32         List<User> users =session.selectList(getUserListCase.getExpected(), getUserListCase);
33         JSONArray array = new JSONArray(users);
34         System.out.println(array.toString());
35         Assert.assertEquals(array.length(), resultJson.length());
36         for (int i = 0; i < resultJson.length(); i++) {
37             JSONObject actual=(JSONObject) array.get(i);
38             JSONObject except=(JSONObject) resultJson.get(i);
39             Assert.assertEquals(actual.toString(), except.toString());
40         }
41     }
42 
43     private JSONArray getJsonResult(GetUserListCase getUserListCase) throws ClientProtocolException, IOException {
44         HttpPost post = new HttpPost(TestConfig.getUserListUrl);
45         JSONObject param = new JSONObject();
46         param.put("sex",getUserListCase.getSex());
47         post.setHeader("content-type","application/json");
48         StringEntity entity = new StringEntity(param.toString(),"utf-8");
49         post.setEntity(entity);
50         //设置cookies
51         TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
52         String result;
53         HttpResponse response = TestConfig.defaultHttpClient.execute(post);
54         result = EntityUtils.toString(response.getEntity(),"utf-8");
55         JSONArray array = new JSONArray(result);
56         return array;
57     }
58 }
 1 package com.test.cases;
 2 
 3 import java.io.IOException;
 4 import java.util.ArrayList;
 5 import java.util.Arrays;
 6 import java.util.List;
 7 
 8 import org.apache.http.HttpResponse;
 9 import org.apache.http.client.ClientProtocolException;
10 import org.apache.http.client.methods.HttpPost;
11 import org.apache.http.entity.StringEntity;
12 import org.apache.http.util.EntityUtils;
13 import org.apache.ibatis.session.SqlSession;
14 import org.json.JSONArray;
15 import org.json.JSONObject;
16 import org.testng.Assert;
17 import org.testng.annotations.Test;
18 
19 import com.test.config.TestConfig;
20 import com.test.pojo.GetUserInfoCase;
21 import com.test.pojo.User;
22 import com.test.utils.DatabaseUtil;
23 
24 public class GetUserInfoTest {
25     @Test(dependsOnGroups = "loginTrue",description = "获取userid为1的用户信息")
26     public void getUserInfo() throws IOException {
27         SqlSession session = DatabaseUtil.getSqlSession();
28         GetUserInfoCase getUserInfoCase = session.selectOne("getUserInfoCase",1);
29         JSONArray resultJson = getJsonResult(getUserInfoCase);
30         User user=session.selectOne(getUserInfoCase.getExpected(), getUserInfoCase);
31         System.out.println(user);
32         List<User> users= new ArrayList<User>();
33         users.add(user);
34         JSONArray jsonArray = new JSONArray(users);
35         JSONArray jsonArray1 = new JSONArray(resultJson.getString(0));
36         Assert.assertEquals(jsonArray.toString(),jsonArray1.toString());
37     }
38 
39     private JSONArray getJsonResult(GetUserInfoCase getUserInfoCase) throws ClientProtocolException, IOException {
40         HttpPost post = new HttpPost(TestConfig.getUserInfoUrl);
41         JSONObject param = new JSONObject();
42         param.put("id",getUserInfoCase.getUserid());
43         post.setHeader("content-type","application/json");
44         StringEntity entity = new StringEntity(param.toString(),"utf-8");
45         post.setEntity(entity);
46         //设置cookies
47         TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
48         String result;
49         HttpResponse response = TestConfig.defaultHttpClient.execute(post);
50         result = EntityUtils.toString(response.getEntity(),"utf-8");
51         List resultList = Arrays.asList(result);
52         JSONArray array = new JSONArray(resultList);
53         return array;
54     }
55 }
 1 package com.test.cases;
 2 
 3 import java.io.IOException;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 import org.apache.http.HttpResponse;
 8 import org.apache.http.client.ClientProtocolException;
 9 import org.apache.http.client.methods.HttpPost;
10 import org.apache.http.entity.StringEntity;
11 import org.apache.http.util.EntityUtils;
12 import org.apache.ibatis.session.SqlSession;
13 import org.json.JSONArray;
14 import org.json.JSONObject;
15 import org.testng.Assert;
16 import org.testng.annotations.Test;
17 
18 import com.test.config.TestConfig;
19 import com.test.pojo.UpdateUserInfoCase;
20 import com.test.pojo.User;
21 import com.test.utils.DatabaseUtil;
22 
23 public class UpdateUserInfoTest {
24     @Test(dependsOnGroups = "loginTrue",description = "更改用户信息")
25     public void updateUser() throws IOException, InterruptedException {
26         SqlSession session = DatabaseUtil.getSqlSession();
27         UpdateUserInfoCase updateUserInfoCase =session.selectOne("updateUserInfoCase", 1);
28         int result =getResult(updateUserInfoCase);
29         User user =    session.selectOne(updateUserInfoCase.getExpected(), updateUserInfoCase);
30         Assert.assertNotNull(user);
31         Assert.assertNotNull(result);
32     }
33     @Test(dependsOnGroups = "loginTrue",description = "删除用户信息")
34     public void deleteUser() throws IOException, InterruptedException {
35         SqlSession session = DatabaseUtil.getSqlSession();
36         UpdateUserInfoCase updateUserInfoCase =session.selectOne("updateUserInfoCase", 2);
37         int result =getResult(updateUserInfoCase);
38         User user =    session.selectOne(updateUserInfoCase.getExpected(), updateUserInfoCase);
39         Assert.assertNotNull(user);
40         Assert.assertNotNull(result);
41     }
42 
43     private int getResult(UpdateUserInfoCase updateUserInfoCase) throws ClientProtocolException, IOException, InterruptedException {
44         HttpPost post = new HttpPost(TestConfig.updateUserInfoUrl);
45         JSONObject param = new JSONObject();
46         param.put("username",updateUserInfoCase.getUsername());
47         param.put("sex",updateUserInfoCase.getSex());
48         param.put("age",updateUserInfoCase.getAge());
49         param.put("permisson",updateUserInfoCase.getPermisson());
50         param.put("isDelete",updateUserInfoCase.getIsDelete());
51         param.put("id",updateUserInfoCase.getUserid());
52         post.setHeader("content-type","application/json");
53         StringEntity entity = new StringEntity(param.toString(),"utf-8");
54         post.setEntity(entity);
55         //设置cookies
56         TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
57         String result;
58         HttpResponse response = TestConfig.defaultHttpClient.execute(post);
59         result = EntityUtils.toString(response.getEntity(),"utf-8");
60         System.out.println(result);
61         Thread.sleep(10000);
62         return  Integer.parseInt(result);
63     }
64 
65 }

10.testng.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="用户管理系统测试套件">
    <test name="用户管理系统测试用例">
        <classes>
            <class name="com.test.cases.LoginTest">
                <methods>
                    <include name="loginTrue"/>
                    <include name="loginFalse"/>
                </methods>
            </class>
            <class name="com.test.cases.AddUserTest">
                <methods>
                    <include name="addUser"/>
                </methods>
            </class>
            <class name="com.test.cases.GetUserInfoTest">
                <methods>
                    <include name="getUserInfo"/>
                </methods>
            </class>
            <class name="com.test.cases.GetUserInfoTest">
                <methods>
                    <include name="getUserInfoList"/>
                </methods>
            </class>
            <class name="com.test.cases.UpdateUserInfoTest">
                <methods>
                    <include name="updateUser"/>
                    <include name="deleteUser"/>
                </methods>
            </class>
        </classes>
    </test>
    <listeners>
        <listener class-name="com.test.config.ExtentTestNGIReporterListener"/>
    </listeners>
</suite>

11.运行接口工厂中的springboot类,启动后,运行测试代码中的testng.xml,运行结束后可以看到测试报告

12.目录结构图

13.git地址:https://github.com/pancakefans/AutoTest.git

原文地址:https://www.cnblogs.com/heyuling/p/12101167.html