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)
原文地址:https://www.cnblogs.com/architectforest/p/14523143.html