请选择 进入手机版 | 继续访问电脑版
本站特色:极好的技术研究氛围!所有技术交流,必有回复!

疯狂Java联盟

 找回密码
 加入联盟
查看: 813|回复: 0

Spring Boot2.0连载(46)-- Spring Boot的单元测试

[复制链接]
发表于 2018-6-5 21:46:33 | 显示全部楼层 |阅读模式
更多Spring Boot2.0的知识敬请期待疯狂软件著作《Spring Boot企业应用实战》上市


项目测试在系统开发中有着十分重要的作用,在大型系统,尤其业务相对复杂的项目中,测试用例就显得尤为重要,它可以避免测试点的遗漏,可以提高测试效率,可以实现自动测试,可以在项目打包前进行测试校验,可以通过测验及时发现因为修改代码导致新的问题的出现,并及时解决,本小节将重点介绍Spring Boot中的项目测试,本篇实例采用了成书时最稳定的版本Spring Boot版本2.0.0.RELEASE,在最新的案例中可以通过,在新版的Spring Boot中,官方推荐使用@SpringBootTest定义测试类。

(1)    定义数据访问层接口。

  1. package org.fkit.springboottest.repository;
  2. import org.fkit.springboottest.bean.Student;
  3. import org.springframework.data.jpa.repository.JpaRepository;

  4. public interface StudentRepository extends JpaRepository<Student, Integer> {
  5.    
  6. }
复制代码



(2)    定义业务层类。
在org.fkit.springboottest.service包下新建一个业务层对象,命名为SchoolService.java,代码如下:
程序清单:codes/05/springboottest/src/main/java/org/fkit/springboottest/service/SchoolService.java
  1. package org.fkit.springboottest.service;
  2. import java.util.List;
  3. import java.util.Map;
  4. import javax.annotation.Resource;
  5. import org.fkit.springboottest.bean.Student;
  6. import org.fkit.springboottest.repository.StudentRepository;
  7. import org.springframework.stereotype.Service;
  8. import org.springframework.transaction.annotation.Transactional;
  9. @Service
  10. public class SchoolService {
  11.    
  12.     // 定义数据访问层接口对象
  13.     @Resource
  14.     private StudentRepository studentRepository;
  15.    
  16.     @Transactional
  17.     public void save(Student stu) {
  18.         studentRepository.save(stu);
  19.     }

  20.     public Student selectByKey(Integer id) {
  21.         return studentRepository.findOne(id);
  22.     }
  23. }
复制代码


(3)    定义控制器类及启动类
在org.fkit.springboottest.controller包先新建一个控制器类命名为StudentController,其代码如下:
程序清单:codes/05/springboottest/src/main/java/org/fkit/springboottest/controller/StudentController.java

  1. package org.fkit.springboottest.controller;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import javax.annotation.Resource;
  5. import org.fkit.springboottest.bean.Student;
  6. import org.fkit.springboottest.service.SchoolService;
  7. import org.springframework.web.bind.annotation.PathVariable;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMethod;
  10. import org.springframework.web.bind.annotation.ResponseBody;
  11. import org.springframework.web.bind.annotation.RestController;
  12. import org.springframework.web.bind.annotation.GetMapping;
  13. import org.springframework.web.bind.annotation.PostMapping;

  14. @RestController
  15. @RequestMapping("/student")
  16. public class StudentController {
  17.     @Resource
  18.     private SchoolService shcoolService;
  19.    
  20.     @PostMapping(value="/save")
  21.     public Map<String,Object> save(@RequestBody Student stu) {
  22.         shcoolService.save(stu);
  23.         Map<String,Object> params = new HashMap<>();
  24.         params.put("code", "success");
  25.         return params;
  26.     }
  27.    
  28.     /**
  29.      * 获取学生信息
  30.      * @param id
  31.      */
  32.     @GetMapping(value="/get/{id}")
  33.     @ResponseBody
  34.     public Student qryStu(@PathVariable(value = "id") Integer id){
  35.         Student stu = shcoolService.selectByKey(id);
  36.         return stu;
  37.     }
  38.    
  39. }
复制代码



(4)    Controller单元测试。
Maven项目为单元测试专门定义了一个包:src/test/java,在src/test/java下的org.fkit.springboottest包下新建一个类命名为StudentControllerTest.java,需要注意的是Spring Boot项目中的测试类,需要在类上定义@RunWith(SpringRunner.class),让测试运行于Spring的测试环境,以及注解@SpringBootTest(classes = App.class),其中App.class是项目的启动类,其代码结构如下所示:
程序清单:codes/05/springboottest/src/test/java/org/fkit/springboottest/StudentControllerTest.java

  1. package org.fkit.springboottest;
  2. import javax.transaction.Transactional;
  3. import org.junit.Before;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.http.MediaType;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import org.springframework.test.web.servlet.MockMvc;
  11. import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
  12. import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
  13. import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
  14. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  15. import org.springframework.web.context.WebApplicationContext;

  16. @RunWith(SpringRunner.class)
  17. @SpringBootTest(classes = App.class)
  18. public class StudentControllerTest {

  19.     // 注入Spring容器
  20.     @Autowired
  21. private WebApplicationContext wac;
  22. // MockMvc实现了对Http请求的模拟
  23.     private MockMvc mvc;
  24.     @Before
  25.     public void setupMockMvc(){
  26.         //初始化MockMvc对象
  27.         mvc = MockMvcBuilders.webAppContextSetup(wac).build();
  28.     }
  29.    
  30.     /**
  31.      * 新增学生测试用例
  32.      * @throws Exception
  33.      */
  34.     @Test
  35.     @Transactional
  36.     public void addStudent() throws Exception{
  37.         String json="{"name":"孙悟空","address":"花果山","age":"700","sex":"男"}";
  38.         mvc.perform(MockMvcRequestBuilders.post("/student/save")
  39.                     .contentType(MediaType.APPLICATION_JSON_UTF8)
  40.                     .accept(MediaType.APPLICATION_JSON_UTF8)
  41.                     .content(json.getBytes()) //传json参数
  42.             )
  43.            .andExpect(MockMvcResultMatchers.status().isOk())
  44.            .andDo(MockMvcResultHandlers.print());
  45.     }

  46.     /**
  47.      * 获取学生信息测试用例
  48.      * @throws Exception
  49.      */
  50.     @Test
  51.     public void qryStudent() throws Exception {
  52.         mvc.perform(MockMvcRequestBuilders.get("/student/get/1")
  53.                     .contentType(MediaType.APPLICATION_JSON_UTF8)
  54.                     .accept(MediaType.APPLICATION_JSON_UTF8)
  55.             )
  56.            .andExpect(MockMvcResultMatchers.status().isOk())
  57.            .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("孙悟空"))
  58.            .andExpect(MockMvcResultMatchers.jsonPath("$.address").value("花果山"))
  59.            .andDo(MockMvcResultHandlers.print());
  60.     }
  61. }
复制代码


在对Controller层(API)做测试,这时候就得用到MockMvc了,你可以不必启动工程就能测试这些接口。MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。接下来对StudentControllerTest类中用到的API进行解释分析:
  • mockMvc.perform执行一个请求,请求可以调用到控制器中的某个方法。
  • MockMvcRequestBuilders.get(“/student/get/1”)构造一个请求,Post请求就用.post方法。
  • contentType(MediaType.APPLICATION_JSON_UTF8)代表发送端发送的数据格式是application/json;charset=UTF-8。
  • accept(MediaType.APPLICATION_JSON_UTF8)代表客户端希望接受的数据类型为application/json;charset=UTF-8。
  • ResultActions.andExpect添加执行完成后的断言。
  • ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看请求的状态响应码是否为200如果不是则抛异常,测试不通过。
  • andExpect(MockMvcResultMatchers.jsonPath("$.name").value("孙悟空"))这里jsonPath用来获取name字段比对是否为孙悟空,不是就测试不通过。
  • ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。



您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

视频、代码、电子书下载
请关注"疯狂图书"公众号
QQ交流1群: 545923995  未满
微信群请扫二维码
QQ交流1群:
545923995
(未满)

小黑屋|手机版|Archiver|疯狂Java联盟 ( 粤ICP备11094030号 )

GMT+8, 2019-1-17 16:37 , Processed in 0.243233 second(s), 6 queries , File On.

快速回复 返回顶部 返回列表