Mockito verify Junit5集成 Mockito
创始人
2024-03-20 08:23:15
0

Mockito 集成 Junit5

在学习Mockito 如何集成 Junit5 之前,先来学习下 Mockito 基础的verify功能。

Maven依赖

本篇博客代码的Maven依赖如下,源码地址

org.springframeworkspring-web6.0.2org.springframeworkspring-core6.0.2org.springframeworkspring-context6.0.2org.apache.commonscommons-lang33.12.0org.mockitomockito-junit-jupiter4.8.1testorg.projectlomboklombok1.18.22compilecom.google.guavaguava31.1-jreorg.mockitomockito-core4.8.1testorg.assertjassertj-core3.22.0test

Mockito Verify

Mockito Verify 方法经常被用于检查校验对象是否发生特定行为 - 即方法. 开发者可在测试方法代码的末尾使用verify方法, 确定是否调用了指定的方法。Mockito Verify主要从以下几个方面对调用行为进行判断

  • 校验是否调用指定方法
  • 校验没有调用其他方法
  • 校验方法调用次数
  • 校验调用方法顺序
  • 校验调用方法的参数

接下来详细学习下 Mockito Verify 相关的API

验证简单调用

  • 验证是否调用指定方法
@Testvoid test1(){List list = mock(ArrayList.class);list.size();// 验证是否调用size 方法verify(list).size();}
  • 验证没有调用其他方法

    @Testvoid test2(){List list = mock(ArrayList.class);// 验证list 对象没发生额外调用verifyNoMoreInteractions(list);}
    
  • 验证从没调用过指定方法

    @Testvoid test3(){List list = mock(ArrayList.class);list.size();//从未调用过clear 方法verify(list,never()).clear();}
    

验证调用次数

  • 验证仅调用一次

        @Testvoid test0(){List list = mock(ArrayList.class);list.size();// times(1), only(),atLeast(1) 都能实现一次调用的验证//verify(list,times(1)).size();//verify(list,only()).size();verify(list,atLeast(1)).size();}
    
  • 验证至少调用次数

    @Testvoid test0(){List list = mock(ArrayList.class);list.size();// 最少一次调用验证verify(list,atLeastOnce()).size();}
    
  • 验证最多调用次数

    @Testvoid test0(){List list = mock(ArrayList.class);list.size();//最多一次verify(list,atMostOnce()).size();// 最多10次verify(list,atMost(10)).size();}
    

验证调用顺序

@Testvoid test3(){List list = mock(ArrayList.class);list.size();list.add("hello");list.clear();InOrder inOrder = Mockito.inOrder(list);inOrder.verify(list).size();inOrder.verify(list).add(anyString());inOrder.verify(list).clear();}

验证调用参数

  • 验证指定参数

        @Testvoid test6(){List list = mock(ArrayList.class);list.add("hello");verify(list).add("hello");// 以下两种 验证参数类型verify(list).add(anyString());verify(list).add(any(String.class));}
    
  • 验证捕获参数

     @Testvoid test7(){List list = mock(ArrayList.class);list.addAll(Lists. newArrayList("someElement"));ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class);verify(list).addAll(captor.capture());// 捕获参数 并验证是否包含特定值final List value = captor.getValue();assertThat(value).contains("someElement");}
    

集成Junit5

有了之前的基础后,接下来来学习下Mockito 如何集成 Junit5,了解Junit5如何对Mockito进行扩展。大致的流程:

  • 首先先创建Junit5扩展,该扩展使用@mock自动创建mock对象,模拟任何对象属性或者方法
  • 然后在Junit5测试类中使用Mockito扩展

应用场景

假设现在有一个项目,团队需要基于SpringBoot MVC的架构模式进行开发。由于业务足够复杂,分工细致。你被要求开发 service层的业务逻辑,Repository数据操作层由其他团队负责,双方根据约定好的接口进行协同开发。

由于你的专业技术能力过硬,开发效率较高,因此已经完成了开发工作。但是其他团队Repository没有完成,只提供了对应的接口。现在您需要对整理流程进行集成测试,此时Mock排上用场。

基础代码

  • User 实体类

    @Data
    @ToString
    @NoArgsConstructor
    public class User {private Integer id;private String name;private int age;public User(String name,int age){this.name = name;this.age  = age;}
    }
    
  • service接口

    import com.andy.spring.junit5.mockito.User;public interface UserService {User register(User user);
    }
    
  • service实现类

    import com.andy.spring.junit5.mockito.User;
    import com.andy.spring.junit5.mockito.repository.UserRepository;
    import com.andy.spring.junit5.mockito.service.UserService;public class DefaultUserService implements UserService {private UserRepository userRepository;public DefaultUserService(UserRepository userRepository) {this.userRepository = userRepository;}@Overridepublic User register(User user) {validate(user);User insertedUser = userRepository.insert(user);return insertedUser;}private void validate(User user) {if(user.getName() == null) {throw new RuntimeException("用户名称不能为空");}if(userRepository.isUsernameAlreadyExists(user.getName())) {throw new RuntimeException("用户名称已存在");}}
    }
    
  • Repository 接口定义

    import com.andy.spring.junit5.mockito.User;public interface UserRepository {User insert(User user);boolean isUsernameAlreadyExists(String userName);}
    

验证测试

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {private UserService userService;@Mockprivate UserRepository userRepository;private User user;//每次运行测试方法都进行初始化@BeforeEachvoid init(){userService = new DefaultUserService(userRepository);//输入任意字符串 参数校验都返回falselenient().when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false);}@Testvoid test1(){user = new User("kobe",40);when(userRepository.insert(any(User.class))).then(new Answer() {int sequence = 1;@Overridepublic User answer(InvocationOnMock invocation) throws Throwable {//模拟插入db后,对ID主键进行赋值User user = (User) invocation.getArgument(0);user.setId(sequence++);return user;}});userService = new DefaultUserService(userRepository);// WhenUser insertedUser = userService.register(user);System.out.println("insertedUser : " + insertedUser);// Then 验证是否调用 insert 方法 参数为userverify(userRepository).insert(user);assertNotNull(user.getId());}
}

以上代码很容易理解,值得注意的是需要在class类上加上**@ExtendWith(MockitoExtension.class)**注解。测试截图

img

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...