spring boot单元测试之三:用mockito在controller/service测试中打桩(spring boot 2.4.3)
一,演示项目的相关信息
1,地址:
https://github.com/liuhongdi/mockitotest
2,功能说明:演示了用mockito在controller/service测试中打桩
3,项目结构:如图:
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/26/spring-boot-dan-yuan-ce-shi-zhi-san-yong-mockito-zai/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,配置文件说明
1,application.yml
#error server: error: include-stacktrace: always #errorlog logging: level: org.springframework.web: trace #mysql spring: datasource: url: jdbc:mysql://127.0.0.1:3306/store?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: lhddemo driver-class-name: com.mysql.cj.jdbc.Driver maximum-pool-size: 12 minimum-idle: 10 idle-timeout: 500000 max-lifetime: 540000 #mybatis mybatis: mapper-locations: classpath:/mapper/*Mapper.xml type-aliases-package: com.example.demo.mapper configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2,pom.xml中的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--mybatis begin--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--mybatis end--> <!--mysql begin--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--mysql end-->
三,java代码说明
1,controller/GoodsController.java
@Controller @RequestMapping("/goods") public class GoodsController { @Resource private GoodsService goodsService; //商品详情 参数:商品id @GetMapping("/one") @ResponseBody public RestResult goodsInfo(@RequestParam(value="goodsid",required = true,defaultValue = "0") Long goodsId) { Goods goods = goodsService.getOneGoodsById(goodsId); if (goods == null) { return RestResult.error(ResponseCode.GOODS_NOT_EXIST); } else { return RestResult.success(goods); } } }
2,service/GoodsService.java
@Service public class GoodsService { @Resource private GoodsMapper goodsMapper; //得到一件商品的信息 public Goods getOneGoodsById(Long goodsId) { System.out.println("get data from mysql"); Goods goodsOne = goodsMapper.selectOneGoods(goodsId); System.out.println(goodsOne); return goodsOne; } //添加一件商品到数据库 public Long addOneGoods(Goods goods) { int insNum = goodsMapper.insertOneGoods(goods); if (insNum == 0) { return 0L; } else { Long goodsId = goods.getGoodsId();//该对象的自增ID return goodsId; } } }
3,result/RestResult.java
/** * @desc: API 返回结果 * @author: liuhongdi * @date: 2020-07-01 11:53 * return : * 0:success * not 0: failed */ public class RestResult implements Serializable { //uuid,用作唯一标识符,供序列化和反序列化时检测是否一致 private static final long serialVersionUID = 7498483649536881777L; //标识代码,0表示成功,非0表示出错 private Integer code; //提示信息,通常供报错时使用 private String msg; //正常返回时返回的数据 private Object data; public RestResult(Integer status, String msg, Object data) { this.code = status; this.msg = msg; this.data = data; } //返回成功数据 public static RestResult success(Object data) { return new RestResult(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg(), data); } public static RestResult success(Integer code,String msg) { return new RestResult(code, msg, null); } //返回出错数据 public static RestResult error(ResponseCode code) { return new RestResult(code.getCode(), code.getMsg(), null); } public static RestResult error(Integer code,String msg) { return new RestResult(code, msg, null); } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
4,service/GoodsServiceTest.java
class GoodsServiceTest { @InjectMocks @Autowired GoodsService goodsService; @Mock GoodsMapper goodsMapper; @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); } @Test @DisplayName("商品service:得到一件商品") void getOneGoodsById() { Goods goodsOne = new Goods(); goodsOne.setGoodsId(13L); goodsOne.setGoodsName("商品名称"); goodsOne.setSubject("商品描述"); goodsOne.setPrice(new BigDecimal(100)); goodsOne.setStock(10); doReturn(goodsOne).when(goodsMapper).selectOneGoods(13L); doReturn(null).when(goodsMapper).selectOneGoods(0L); Goods goodsRet = goodsService.getOneGoodsById(13L); assertThat(goodsRet.getGoodsId(), equalTo(13L)); Goods goodsRet2 = goodsService.getOneGoodsById(0L); assertThat(goodsRet2, equalTo(null)); } @Test @DisplayName("商品service:测试添加一件商品") void addOneGoods() { Goods goodsOne = new Goods(); goodsOne.setGoodsId(13L); goodsOne.setGoodsName("商品名称"); goodsOne.setSubject("商品描述"); goodsOne.setPrice(new BigDecimal(100)); goodsOne.setStock(10); Goods goodsTwo = new Goods(); goodsTwo.setGoodsId(12L); goodsTwo.setGoodsName("商品名称"); goodsTwo.setSubject("商品描述"); goodsTwo.setPrice(new BigDecimal(100)); goodsTwo.setStock(10); doReturn(1).when(goodsMapper).insertOneGoods(goodsOne); doReturn(0).when(goodsMapper).insertOneGoods(goodsTwo); Long goodsId = goodsService.addOneGoods(goodsOne); assertThat(goodsId, equalTo(13L)); Long goodsIdFail = goodsService.addOneGoods(goodsTwo);; assertThat(goodsIdFail, equalTo(0L)); } }
5,controller/GoodsControllerTest.java
@AutoConfigureMockMvc @SpringBootTest class GoodsControllerTest { @InjectMocks @Autowired private GoodsController goodsController; @Autowired private MockMvc mockMvc; @Mock GoodsService goodsService; @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); } @Test @DisplayName("商品controller:得到一件商品") void goodsInfo() throws Exception { Goods goodsOne = new Goods(); goodsOne.setGoodsId(13L); goodsOne.setGoodsName("商品名称"); goodsOne.setSubject("商品描述"); goodsOne.setPrice(new BigDecimal(100)); goodsOne.setStock(10); doReturn(goodsOne).when(goodsService).getOneGoodsById(any()); MvcResult mvcResult = mockMvc.perform(get("/goods/one?goodsid=13") .contentType(MediaType.APPLICATION_FORM_URLENCODED)) .andExpect(status().isOk()) .andReturn(); String content = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); System.out.println(content); int code = JsonPath.parse(content).read("$.code"); assertThat(code, equalTo(0)); int goodsId = JsonPath.parse(content).read("$.data.goodsId"); assertThat(goodsId, equalTo(13)); } @Test @DisplayName("商品controller:得到一件商品:不存在") void goodsInfonull() throws Exception { doReturn(null).when(goodsService).getOneGoodsById(0L); MvcResult mvcResult = mockMvc.perform(get("/goods/one?goodsid=0") .contentType(MediaType.APPLICATION_FORM_URLENCODED)) .andExpect(status().isOk()) .andReturn(); String content = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); System.out.println(content); int code = JsonPath.parse(content).read("$.code"); assertThat(code, equalTo(800)); } }
6,其他相关代码可访问github
四,测试效果
1,测试service:
2,测试controller
五,查看spring boot的版本:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.3)