mockito+junit完成单元测试

[复制链接]
发表于 2025-12-31 15:18:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一:单元测试的特点



  • 共同断言利用(可以杜绝System.out)
  • 可以重复实行
  • 不依靠情况
  • 不会对数据产生影响
  • spring的上下文情况不是必须的
  • 一样寻常都必要共同mock类框架来实现
二:常用的mock类框架 

mockito
官网:Mockito framework site
别的如今像powermock和JMockito如今都不常用了;
三:Mockito的单独利用

(1)mock对象和spy对象

方法插桩
方法不插桩
作用对象
最佳实践
mock
实行插桩逻辑
返回mock对象的默认值
类、接口
被测试类或其依靠
spy
实行插桩逻辑
调用真实方法
类、接口
被测试类
(2)初始化mock/spy对象的方式

方法一
方法二
方法三
junit4
@RunWith(MockitoJUnitRunner.class)+@Mock等注解
Mockito.mock(X.class)等静态方法
MockitoAnnotations.openMocks(this)+@Mock等注解
junit5
@ExtendWith(MockitoExtension.class)+@Mock等注解
 四:详细实例操纵

Controller层:
  1. @Slf4j
  2. @RestController
  3. @Validated
  4. public class UserController{
  5.     @Resource
  6.     private UserService userService;
  7.     @GetMapping("/selectById")
  8.     public UserVO selectById(@NotNull Long userId){
  9.         return userService.selectById(userId);
  10.     }
  11.     @PostMapping("/add")
  12.     public String add(@RequestBody @Validated UserAddReq addReq){
  13.         userService.add(addReq.getUsername(),addReq.getPhone(),addReq.getfeatures());
  14.         return ok;
  15.     }
  16. }
复制代码
方法一:@ExtendWith(MockitoExtension.class)+@Mock等注解
  1. @ExtendWith(MockitoExtension.class)
  2. public class InitMockSpyMethod1{
  3.     @mock
  4.     private UserService mockUserService;
  5.     @Spy
  6.     private UserService spyUserService;
  7.     @Test
  8.     public void test1(){
  9.         //true     判断某对象是不是mock对象
  10.         System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
  11.         //false     判断某对象是不是apy对象
  12.         System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
  13.         //true     判断某对象是不是spy对象
  14.         System.out.println("Mockito.mockingDetails(spyUserService).isSpy() = " + Mockito.mockingDetails(spyUserService).isSpy());
  15.         //true     判断某对象是不是spy对象,因为spy是一种特殊的mock(spy对象是另一种不同类型的mock对象)
  16.         System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetail(spyUserService).isMock());
  17.     }
  18. }
复制代码
spy对象是一种特别的mock对象
方法二:Mockito.mock(X.class)等静态方法
  1. public class InitMockSpyMethod1{
  2.     private UserService mockUserService;
  3.     private UserService spyUserService;
  4.     @BeforeEach
  5.     public void init(){
  6.         mockUserService = Mockito.mock(UserService.class);
  7.         spyUserService =  Mockito.spy(UserService.class);
  8.     }
  9.    
  10.     @Test
  11.     public void test1(){
  12.         System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
  13.         System.out.println("Mockito.mockingDetails(mockUserService).isSpy() = " + Mockito.mockingDetails(mockUserService).isSpy());
  14.         System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetails(spyUserService).isMock());
  15.     }
  16. }
复制代码
方法三:MockitoAnnotations.openMocks(this)+@Mock等注解
  1. public class InitMockSpyMethod1{
  2.     @mock
  3.     private UserService mockUserService;
  4.     @Spy
  5.     private UserService spyUserService;
  6.     @BeforeEach
  7.     public void init(){
  8.         MockitoAnnotations.openMocks(this);
  9.     }
  10.    
  11.     @Test
  12.     public void test1(){
  13.         //true     判断某对象是不是mock对象
  14.         System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
  15.         //false     判断某对象是不是apy对象
  16.         System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
  17.         //true     判断某对象是不是spy对象
  18.         System.out.println("Mockito.mockingDetails(spyUserService).isSpy() = " + Mockito.mockingDetails(spyUserService).isSpy());
  19.         //true     判断某对象是不是spy对象,因为spy是一种特殊的mock(spy对象是另一种不同类型的mock对象)
  20.         System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetail(spyUserService).isMock());
  21.     }
  22. }
复制代码
五:参数匹配

参数匹配指的是:通过方法署名(参数)来指定哪些方法调用必要处置惩罚被处置惩罚(插桩、verify验证)
对于mock对象不会调用真实方法,直接返回mock对象的默认值;
默认值(int)、null(UserVO)、空聚集(list)

六:方法插桩

指定调用某个方法时的举动(stubbing),到达相互隔离的目标

  1. /**
  2. *测试插桩时的参数匹配
  3. */
  4. @Test
  5. public void test2(){
  6.     UserUpdateReq userUpdateReq1 = new UserUpdateReq();
  7.     userUpdateReq1.setId(1L);
  8.     userUpdateReq1.setPhone("1L");
  9.     //指定参数为userUpdateReq1时调用mockUserService.modifyById(userUpdateReq1);
  10.     Mockito.doReturn(99).when(mockUserService).modifyById(userUpdateReq1);
  11.     int result1 = mockUserService.modifyById(userUpdateReq1);
  12.     //运行结果为99
  13.     System.out.println("result1 = " + result1);
  14.    
  15.     UserUpdateReq userUpdateReq2 = new UserUpdateReq();
  16.     userUpdateReq2.setId(2L);
  17.     userUpdateReq2.setPhone("2L");
  18.     int result2 = mockUserService.modifyById(userUpdateReq2);
  19.     //运行结果为0
  20.     System.out.println("result2 = " + result2);
  21. }
复制代码
总结:
是告诉mockito当传入的是下面的参数这个范例时,才对其进插桩,若不是这个值,则不消对它举行插桩

若想要拦截某种范例的恣意对象,则必要运用到:
ArgumentMatchers.any拦截UserUpdateReq范例的恣意对象

 校验:
 add方法调用一次,校验通过。
  1.   private UserService mockUserService;
  2.     @Test
  3.     public void test4(){
  4.         List<String> features = new ArrayList<>();
  5.         mockUserService.add("实验","123",festures);
  6.         //校验参数为"乐之者","123",festures,features的add方法调用了1次
  7.         Mockito.verify(mockUserService,Mockito.times(2)).add("实验","123",festures);
  8.         //报错  ,要么都用要么就都别用
  9.        // Mockito.verify(mockUserService,Mockito.times(2)).add("实验","123",festures);
  10.         //此时可以校验通过
  11.          Mockito.verify(mockUserService,Mockito.times(2)).add(anyString(),anyString(),anyList());
  12.     }
  13.    
  14. }
复制代码
但是有一点必要牢记的,除了any,另有(anyLong,anyString...),留意他们都不包罗null,如果传null,照旧不能被匹配的。
通过插桩,指定方法的返回值:


void返回值方法插桩 :
 

插桩的两种方式:





多次插桩:



此中when(mockList.size()).thenReturn(1).thenReturn(2).thenReturn(3)可以简写为when(mockList.size()).thenReturn(1,2,3);
thenAnswer指定插桩逻辑:


实行真正的原始方法:


verify的利用:




@InjectMocks注解的利用

1.被@InjectMocks标注的属性必须是实现类,由于mockito会创建对应的实例对象,默认创建的对象就是未颠末mockito处置惩罚的平常对象。因此常共同@spy注解使其变成默认调用真实方法的mock对象。
2.mockito会利用spy,终极的结果就是,会把userFeatureService给注入到InjectMocks标注的变量所对应的对象内里去。

注入的原理:


回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表