Mock测试(测试service层举例)

例子:向事件表中插入事件数据,若该事件涉及到的实体在实体表中不存在,则将实体再插入实体表,同时向实体和事件关系表插入数据。事件和实体用随机生成的UUID作为唯一标识。

service层实现:

// EventService.java
@Service
public class EventService {
    @Autowired
    private EventMapper eventMapper;

    @Autowired
    private EntityService entityService;

    public void insertEvent(String title, LocalDateTime eventTime, String nation, String entityName) {
        String eventUuid = UUID.randomUUID().toString();

        //创建事件
        EventEntity eventEntity = new EventEntity();
        eventEntity.setEventUuid(eventUuid);
        eventEntity.setTitle(title);
        eventEntity.setEventTime(eventTime);
        eventEntity.setNation(nation);

        //向事件表插入事件
        eventMapper.insertEvent(eventEntity);

        //判断实体表是否存在实体,不存在则实体表插入实体、实体和事件关系表插入关系
        Boolean flag = entityService.insertEntityIfNotExists(entityName, eventUuid);

        if(flag){
            System.out.println("实体不存在,插入");
        }else {
            System.out.println("实体存在,不插入");
        }
    }

}

// EntityService.java
@Service
public class EntityService {
    @Autowired
    private EntityMapper entityMapper;

    @Autowired
    private AssociationMapper associationMapper;

    public Boolean insertEntityIfNotExists(String entityName, String eventUuid) {

        String entityUuid = UUID.randomUUID().toString();

        //根据实体名查询数据
        List<Entity> existingEntity = entityMapper.findByEntityName(entityName);

        //没有该数据则执行插入逻辑
        if (existingEntity.size() == 0) {

            Entity entityEntity = new Entity();
            entityEntity.setEntityUuid(entityUuid);
            entityEntity.setEntityName(entityName);

            //关系表的插入
            associationMapper.insert(entityUuid, eventUuid);
            
            //实体表的插入
            entityMapper.insertEntity(entityEntity);
            return true;
        }
        else{
            return false;
        }
    }
}

       有了这样一个例子之后,现在我想知道我 EventService 里面的insertEvent方法逻辑对不对,当然可以直接进行测试,但是这种情况下,我们会对数据库进行操作,既有访问数据库,又有插入数据库的操作,很多时候可能是我们不愿意看到的。此外还要启动整个项目,若当项目过大时,启动一次项目耗时也是不愿意看到的情况。

        这个时候mock测试的作用就体现出来了。mock我简单粗暴的在这种情况下的理解就是“模拟”,将你不愿意真正执行的函数进行mock模拟,模拟的函数不会真正的去执行函数内部代码,而是通过你给定函数形参和指定返回值进行下一步的操作即可。

        以下就是针对“EventService 里面的insertEvent方法逻辑对不对”写的mock单元测试代码:
 

package com.example.springbootexam.service;

import com.example.springbootexam.mapper.EventMapper;
import com.example.springbootexam.pojo.EventEntity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.time.LocalDateTime;


import static org.mockito.Mockito.*;


/**
 * ClassName:EventServiceTest
 * Package:com.example.springbootexam.service
 * Description:
 *
 * @Date:2023/10/9 14:33
 * @Author:QiTao
 */

@RunWith(MockitoJUnitRunner.class)
public class EventServiceTest {

    @InjectMocks
    private EventService eventService;

    @Mock
    private EventMapper eventMapper;

    @Mock
    private EntityService entityService;

    @Test
    public void testInsertEvent() {
        // 创建测试数据
        String title = "ttt卡尔·文森号航空母舰于美国西海岸航行";
        LocalDateTime eventTime = LocalDateTime.of(2023, 10, 7, 0, 0);
        String nation = "美国西海岸";
        String entityName = "卡尔·文森号航空母舰";
        String eventUuid = "77f66316-c276-49c8-96fa-73e041efc8f7";

        // 模拟eventMapper的行为
        doNothing().when(eventMapper).insertEvent(any(EventEntity.class));

        // 模拟entityService的行为
        when(entityService.insertEntityIfNotExists(eq(entityName), any(String.class))).thenReturn(true);

        // 调用待测试的方法
        eventService.insertEvent(title, eventTime, nation, entityName);

        // 验证行为是否符合预期
        verify(entityService, times(1)).insertEntityIfNotExists(eq(entityName), any(String.class));
        verify(eventMapper, times(1)).insertEvent(any(EventEntity.class));
    }
}


1、@RunWith(MockitoJUnitRunner.class)

就是做一些配置吧,固定写法就没深究。

2、@InjectMocks注解

都说是“打桩”,我简单理解就是你要测试哪个类就给哪个类加这个注解(定位?)

3、@Mock注解

就是对你需要模拟的函数所在的类上加的,比如这里,我想模拟eventMapper的insertEvent插入函数和entityService的insertEntityIfNotExists函数,就在这两个类上加@Mock。

这就是基本的固定套路了。后面便是test逻辑的编写。

4、doNothing()

就是告诉编辑器遇到这个函数别真去执行其中代码。

5、when(entityService.insertEntityIfNotExists(eq(entityName), any(String.class))).thenReturn(true);

我觉得就是“当”遇到insertEntityIfNotExists时就返回(thenReturn)true就行了。至于其中的eq(entityName)就是期望代码运行时的参数和我测试数据的值一致,不一致就抛异常,any(String.class)就是指定string类型的任意值就行。

6、verify(eventMapper, times(1)).insertEvent(any(EventEntity.class));

验证insertEvent是否是执行了一次(不是真的执行代码了)。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值