Junit5+Mock

base project

1,pom依赖

<parent>
    <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.6.11</version>
     <relativePath/>
 </parent>
 
<dependencies>
   <!--添加mysql依赖-->
    <dependency>
        <groupId>org.mariadb.jdbc</groupId>
        <artifactId>mariadb-java-client</artifactId>
        <version>2.7.2</version>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>

    <!--单元测试-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!--junit4-->
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

2,application.yaml

server:
  port: 8896

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mariadb://local_IP_replace:3306/junit?serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
    driver-class-name: org.mariadb.jdbc.Driver

3,controller

@RestController
@RequestMapping("/ele")
public class EleController {

    private final IEleService eleService;


    @Autowired
    public EleController(IEleService eleService) {
        this.eleService = eleService;
    }

    @GetMapping(value = "/selectEleById")
    public Result<Object> selectEleById(@RequestParam(value = "orderId") int orderId) {
        Object object = eleService.selectEleById(orderId);
        return Result.success(object);
    }

    @GetMapping(value = "/selectEleByIdAndName")
    public Result<Object> selectEleByIdAndName(
            @RequestParam(value = "id") int id, @RequestParam(value = "name") String name) {
        Object object = eleService.selectEleByIdAndName(id,name);
        return Result.success(object);
    }
}

4,service

public interface IEleService {
    Object selectEleById(int orderId);
    Object selectEleByIdAndName(int id, String name);
    void process();
    int searchData();
    String searchDataById(int orderId);
}
@Service
public class EleService implements IEleService {

    @Autowired
    private IElementsMapper elementsMapper;

    @Override
    public Object selectEleById(int orderId) {
        ElementsDO elementsDO = elementsMapper.selectById(orderId);
        return elementsDO;
    }

    @Override
    public Object selectEleByIdAndName(int id, String name) {
        LambdaQueryWrapper<ElementsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElementsDO::getId, id);
        queryWrapper.eq(ElementsDO::getElementName, name);
        ElementsDO elementsDO = elementsMapper.selectOne(queryWrapper);
        return elementsDO;
    }

    @Override
    public void process() {
        System.out.println("process");
    }

    @Override
    public int searchData() {
        return 0;
    }

    @Override
    public String searchDataById(int orderId) {
        return ""+orderId;
    }
}

5,mapper

@Mapper
public interface IElementsMapper extends BaseMapper<ElementsDO> {
}

6,entity

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName("ELEMENTS")
public class ElementsDO implements Serializable {
    /**
     * id
     */
    @TableId(value = "ID", type = IdType.AUTO)
    private Integer id;
    /**
     * 要素代码
     */
    @TableField(value = "ELEMENT_CODE")
    private String elementCode;
    /**
     * 要素名称
     */
    @TableField(value = "ELEMENT_NAME")
    private String elementName;
    /**
     * 单位
     */
    @TableField(value = "UNIT")
    private String unit;
}

7,controller返回封装对象

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> {
    private int code;
    private String msg="success";
    private T data;

    /**
     *  成功时候的调用
     * */

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }

    public static<T> Result<T> success(T data){
        return new Result<T>(data);
    }

    /**
     *  失败时候的调用
     * */
    public static  <T> Result<T> error(CodeMsg codeMsg){
        return new Result<T>(codeMsg);
    }

    private Result(T data) {
        this.data = data;
    }

    private Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private Result() {
    }

    private Result(CodeMsg codeMsg) {
        if(codeMsg != null) {
            this.code = codeMsg.getCode();
            this.msg = codeMsg.getMsg();
        }
    }


    /**
     * BindingResult统一处理
     */
    public static Result resolveBindResult(BindingResult bindingResult){
        StringBuilder stringBuilder = new StringBuilder();
        for (String s : bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toList())) {
            stringBuilder.append(",").append(s);
        }
        return Result.error(new CodeMsg(502,stringBuilder.toString().substring(1)));
    }

    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Result [code=" + code + ", msg=" + msg + ", data=" + data + "]";
    }

}

Mock初始化

方式1

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class Init1 {
    //初始化模拟对象
    @Mock
    private EleService eleService;
    //初始化真实对象
    @Spy
    private EleService eleService2;

    @Test
    public void test1(){
        boolean mock = Mockito.mockingDetails(eleService).isMock();
        System.out.println(mock);

        boolean mock1 = Mockito.mockingDetails(eleService2).isSpy();
        System.out.println(mock1);
    }
}

方式2

import org.junit.jupiter.api.BeforeEach;
@ExtendWith(MockitoExtension.class)
public class Init2 {
    private EleService eleService;
    //初始化
    @BeforeEach
    public void init() {
        eleService = Mockito.mock(EleService.class);
    }

    @Test
    public void test1(){
        //判断对象是否为muck对象
        boolean mock = Mockito.mockingDetails(eleService).isMock();
        System.out.println(mock);
    }
}

方式3

import org.junit.jupiter.api.BeforeEach;
@ExtendWith(MockitoExtension.class)
public class Init3 {
    //初始化模拟对象
    @Mock
    private EleService eleService;
    //初始化真实对象
    @Spy
    private EleService eleService2;

    //初始化
    @BeforeEach
    public void init() {
        //初始化当前类对象下的相关mock
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void test1(){
        boolean mock = Mockito.mockingDetails(eleService).isMock();
        System.out.println(mock);

        boolean mock1 = Mockito.mockingDetails(eleService2).isSpy();
        System.out.println(mock1);
    }
}

Mock默认返回值

int默认返回0,对象默认返回null,集合默认返回空集合(空的ArrayList、空的HashSet、空的HashMap)

@ExtendWith(MockitoExtension.class)
public class MockMethod1 {
    //初始化模拟对象
    @Mock
    private EleService eleService;

    @Test
    public void test1(){
        //Mock对象返回默认值,不会调用真正方法
        Object o1 = eleService.selectEleById(1);//null
        System.out.println(o1);
    }
}

Mock参数设置

@ExtendWith(MockitoExtension.class)
public class MockMethod1 {
    //初始化模拟对象
    @Mock
    private EleService eleService;

    @Test
    public void test1(){
        /**
         * 插桩,只拦截参数为1
         */
        //指定参数为1时,selectEleById方法时返回new Object()
        Mockito.doReturn(new Object()).when(eleService).selectEleById(1);
        Object o2 = eleService.selectEleById(1);
        System.out.println(o2);//java.lang.Object@16b2bb0c
    }

    @Test
    public void test2(){
        /**
         * 插桩,拦截selectEleById()的任意参数值
         */
        Mockito.doReturn(new Object()).when(eleService).selectEleById(ArgumentMatchers.any(Integer.class));
        Object o2 = eleService.selectEleById(2);
        System.out.println(o2);//java.lang.Object@c7045b9
    }
}

有返回值时mock

 /**
 * 先执行方法还是先返回
 */
@Test
public void test5(){
    //直接返回,不管是mock还是spy都不执行
    Mockito.doReturn(null).when(eleService).selectEleById(1);
    eleService.selectEleById(1);

    //spy会先执行一次方法,再返回
    Mockito.when(eleService.selectEleById(1)).thenReturn(new Object());
    eleService.selectEleById(1);
}

void类型方法返回值mock

/**
* doNothing()用于void类型返回值
 */
@Test
public void test6(){
    //doNothing()用于void类型返回值,表示调用eleService.process()时什么也不做
    Mockito.doNothing().when(eleService).process();
    eleService.process();
    //验证调用process()次数
    Mockito.verify(eleService, Mockito.times(1)).process();
}

doThrow()用于抛出异常

@Test
public void test7(){
    //eleService.selectEleById()方法参数为任意int时,抛出RuntimeException
    Mockito.doThrow(RuntimeException.class).when(eleService).selectEleById(Mockito.anyInt());
    //执行时会报RuntimeException异常
    eleService.selectEleById(1);
}

断言

/**
* 断言
 */
@Test
public void test4(){
    //插桩,只拦截参数为1
    Mockito.doReturn(null).when(eleService).selectEleById(1);
    
    //junit5断言:预期与实际相等就通过
    Assertions.assertEquals(null,eleService.selectEleById(1));
    
	//junit4断言:预期与实际相等就通过
    Assert.assertEquals(null,eleService.selectEleById(1));
}

模拟多次调用返回值

@Test
public void test8(){
    //当 searchData()方法被调用时,依次返回 1、2、3
    //如果调用次数超过模拟的返回值数量(这里是 3 次),则后续调用会返回最后一个值3
    Mockito.when(eleService.searchData()).thenReturn(1,2,3);
    //第一次调用 searchData(),期望返回值为 1
    Assertions.assertEquals(1,eleService.searchData());
    Assertions.assertEquals(2,eleService.searchData());
    Assertions.assertEquals(3,eleService.searchData());
    //第四次调用 searchData(),由于模拟的返回值只有 3 个,后续调用会返回最后一个值3
    Assertions.assertEquals(3,eleService.searchData());
}

thenAnswer实现指定逻辑

@Test
public void test9(){
    //thenAnswer实现指定逻辑
    Mockito.when(eleService.searchDataById(Mockito.anyInt())).thenAnswer(new Answer<String>() {
        @Override
        public String answer(InvocationOnMock invocation) throws Throwable {
            //获取插桩方法第几个参数值
            Integer argument = invocation.getArgument(0, Integer.class);
            return String.valueOf(argument * 100);
        }
    });

    String s = eleService.searchDataById(2);
    //断言
    Assertions.assertEquals("200",s);
}

thenCallRealMethod()执行真实方法

@Test
public void test10(){
    //thenCallRealMethod()执行真实方法,相当于spy对象执行方法
    Mockito.when(eleService.searchDataById(Mockito.anyInt())).thenCallRealMethod();
    Object o = eleService.searchDataById(1);
    System.out.println(o);
}

验证方法被调用次数

@Test
public void test11(){
    Object o = eleService.searchDataById(1);
    //验证方法是否被调用几次
    Mockito.verify(eleService,Mockito.times(1)).searchDataById(1);
}

@InjectMocks注解

@ExtendWith(MockitoExtension.class)
public class MockMethod3 {
    //EleService中需要IElementsMapper对象
    //@InjectMocks注解的变量中需要用到的mock或spy对象,会自动将当前类中mock或spy成员注入
    @InjectMocks
    private EleService eleService;

    @Mock
    private IElementsMapper elementsMapper;

    @Test
    public void test1(){
        //设置mock返回值
        ElementsDO elementsDO = new ElementsDO();
        elementsDO.setElementName("java");
        elementsDO.setElementCode("1234");
        elementsDO.setId(1);
        elementsDO.setUnit("-");
        Mockito.doReturn(elementsDO).when(elementsMapper).selectById(Mockito.anyInt());

        //执行测试
        Object o1 = eleService.selectEleById(1);

        //ElementsDO(id=1, elementCode=1234, elementName=java, unit=-)
        System.out.println(o1);
    }
}

被mock的service类中方法

@Service
public class EleService implements IEleService {

    @Autowired
    private IElementsMapper elementsMapper;

    @Override
    public Object selectEleById(int orderId) {
        ElementsDO elementsDO = elementsMapper.selectById(orderId);
        return elementsDO;
    }
}

@SpringBootTest

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
//spring运行环境
@RunWith(SpringRunner.class)
//标识当前类为测试类
@SpringBootTest
class SpringbootDemoApplicationTests {
    @Autowired
    private IEleService eleService;

    @Test
    void contextLoads() {
        Object o = eleService.selectEleById(1);
        //ElementsDO(id=1, elementCode=001, elementName=name, unit=--)
        System.out.println(o);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值