zoukankan      html  css  js  c++  java
  • spring boot单元测试之三:用mockito在controller/service测试中打桩(spring boot 2.4.3)

    一,演示项目的相关信息

    1,地址:

    https://github.com/liuhongdi/mockitotest

    2,功能说明:演示了用mockito在controller/service测试中打桩

    3,项目结构:如图:

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: 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)
  • 相关阅读:
    python标准库学习-SimpleHTTPServer
    迁移cnblog博客
    zabbix监控使用
    20 个 OpenSSH 最佳安全实践
    编写基本的 udev 规则
    Linux.Siggen.180
    在 CentOS 7.0 上安装配置 Ceph 存储
    常用 GDB 命令中文速览
    Kubernetes TLS认证
    音乐下载api
  • 原文地址:https://www.cnblogs.com/architectforest/p/14523143.html
Copyright © 2011-2022 走看看