第三十五章:SpringBoot与单元测试的小秘密

感谢作者:https://www.jianshu.com/p/d8f844711bf4


本章目的

基于SpringBoot平台整合Junit分别完成客户端服务端单元测试

构建项目

添加相关依赖Web、MySQL、JPA、Druid、Lombok

    <dependencies>
        <!--data jpa依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>
        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--MySQL依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <!--<scope>provided</scope>-->
        </dependency>
        <!--springboot程序测试依赖,创建项目默认添加-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


准备并配置数据库

good_infos

application.yml

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
    username: root
    password: root
    druid:
      #最大活跃数
      maxActive: 20
      #初始化数量
      initialSize: 1
      #最大连接等待超时时间
      maxWait: 60000
      #打开PSCache,并且指定每个连接PSCache的大小
      poolPreparedStatements: false
      maxPoolPreparedStatementPerConnectionSize: 20
      #通过connectionProperties属性来打开mergeSql功能;慢SQL记录
      #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      minIdle: 1
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: select 1 from dual
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      #配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
      filters: stat, wall
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true


构建实体

/**
 * @author Ray
 * @date 2018/6/30 0030
 * 商品基本信息实体
 */
@Data
@Entity
@Table(name = "good_infos")
public class GoodInfoEntity implements Serializable {

    //商品编号
    @Id
    @Column(name = "tg_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer tgId;

    //商品类型编号
    @Column(name = "tg_type_id")
    private Integer typeId;

    //商品标题
    @Column(name = "tg_title")
    private String title;

    //商品价格
    @Column(name = "tg_price")
    private double price;

    //商品排序
    @Column(name = "tg_order")
    private int order;
    
}


构建测试控制器

/**
 * @author Ray
 * @date 2018/6/30 0030
 */
@RestController
public class TestController {

    /**
     * 商品基本信息数据接口
     */
    @Autowired
    private GoodInfoJPA goodInfoJPA;

    /**
     * 查询首页内容
     */
    @RequestMapping(value = "/index")
    public String index(String name){
        return "this is index page" + name;
    }

    /**
     * 查询全部商品
     */
    @RequestMapping(value = "/all")
    public List<GoodInfoEntity> selectAll(){
        return goodInfoJPA.findAll();
    }

    /**
     * 查询商品详情
     */
    @RequestMapping(value = "/detail", method = RequestMethod.GET)
    public Optional<GoodInfoEntity> selectOne(Integer tgId){
        return goodInfoJPA.findById(tgId);
    }
}


编写单元测试

/**
 * 单元测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Lesson35ApplicationTests {

    /**
     * 模拟mvc测试对象
     * 这个类是Spring为我们提供模拟SpringMVC请求的实例类
     */
    private MockMvc mockMvc;

    /**
     * web 项目上下文
     */
    @Autowired
    private WebApplicationContext webApplicationContext;

    /**
     * 商品业务数据接口
     */
    @Autowired
    private GoodInfoJPA goodInfoJPA;

    /**
     * 所有测试方法执行之前执行该方法
     */
    @Before
    public void before(){
        // 获取mockmvc对象实例
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    /**
     * 测试访问/index地址(已测试)
     */
    @Test
    public void testIndex() throws Exception {
        MvcResult mvcResult = mockMvc
                .perform( //perform方法其实只是为了构建一个请求,并且返回ResultActions实例,该实例则是可以获取到请求的返回内容。
                        MockMvcRequestBuilders.get("/index")
                        //param方法用于在发送请求时携带参数,当然除了该方法还有很多其他的方法,大家可以根据实际请求情况选择调用。
                        .param("name", "admin")
                )
                //andReturn方法则是在发送请求后需要获取放回时调用,该方法返回MvcResult对象,该对象可以获取到返回的视图名称、返回的Response状态、获取拦截请求的拦截器集合等。
                .andReturn();
        //MvcResult对象实例获取的MockHttpServletResponse对象从而才得到的Status状态码。
        int status = mvcResult.getResponse().getStatus();
        //同样也是使用MvcResult实例获取的MockHttpServletResponse对象从而得到的请求返回的字符串内容。
        String responseString = mvcResult.getResponse().getContentAsString();

        //使用Junit内部验证类Assert判断返回的状态码是否正常为200
        Assert.assertEquals("请求错误", 200, status);
        //判断返回的字符串是否与我们预计的一样。
        Assert.assertEquals("返回结果不一致", "this is index pageadmin", responseString);
    }

    @Test
    public void testAll() throws Exception {
        MvcResult mvcResult = mockMvc
                .perform(
                        MockMvcRequestBuilders.get("/all")
                )
                .andReturn();
        int status = mvcResult.getResponse().getStatus();
        String responseString = mvcResult.getResponse().getContentAsString();

        Assert.assertEquals("return status not equals 200", 200, status);
        System.out.println(responseString);
    }

    /**
     * 测试查询详情(已测试)
     */
    @Test
    public void testDetail() throws Exception {
        MvcResult mvcResult = mockMvc
                .perform(
                        //需要请求的本项目的相对路径
                        MockMvcRequestBuilders.get("/detail")
                        //param方法用于在发送请求时携带参数
                        .param("tgId", "1")
                )
                //发送请求后需要获取放回时调用
                .andReturn();

        // 输出拦截器
        HandlerInterceptor[] interceptors = mvcResult.getInterceptors();
        System.out.println("拦截器: " + interceptors[0].getClass().getName());

        int status = mvcResult.getResponse().getStatus();
        String responseString = mvcResult.getResponse().getContentAsString();
        System.out.println("返回内容: " + responseString);
        Assert.assertEquals("return status not equals 200", 200, status);
    }

    /**
     * 测试添加商品基本信息(已测试)
     */
    @Test
    public void testInsert(){
        /**
         * 商品基本信息实体
         */
        GoodInfoEntity goodInfoEntity = new GoodInfoEntity();
        goodInfoEntity.setTitle("西红柿3");
        goodInfoEntity.setOrder(23);
        goodInfoEntity.setPrice(5.83);
        goodInfoEntity.setTypeId(3);
        goodInfoJPA.save(goodInfoEntity);

        /**
         * 测试是否添加成功
         * 验证主键是否存在
         */
        Assert.assertNotNull(goodInfoEntity.getTgId());
    }

    /**
     * 测试删除商品基本信息(已测试)
     */
    @Test
    public void testDelete(){
        // 根据主键删除
        goodInfoJPA.deleteById(3);

        // 验证数据库是否存在删除
        Assert.assertNull(goodInfoJPA.findById(3));
    }

    @Test
    public void contextLoads() {
    }

}

测试index请求

    1、情况一(结果不一致)




    2、情况二(请求错误)




    3、情况三(正常)



测试添加操作




测试查询操作



测试删除操作



猜你喜欢

转载自blog.csdn.net/q343509740/article/details/80867992