自己做网站 怎么解决安全问题,全网营销型网站建设,溧阳手机网站哪里做,网站建设网络推广书生一#xff1a;单元测试的特点
配合断言使用#xff08;可以杜绝System.out#xff09;可以重复执行不依赖环境不会对数据产生影响spring的上下文环境不是必须的一般都需要配合mock类框架来实现
二#xff1a;常用的mock类框架
mockito
官网#xff1a;Mockito framew…一单元测试的特点
配合断言使用可以杜绝System.out可以重复执行不依赖环境不会对数据产生影响spring的上下文环境不是必须的一般都需要配合mock类框架来实现
二常用的mock类框架
mockito
官网Mockito framework site
另外现在像powermock和JMockito现在都不常用了
三Mockito的单独使用
1mock对象和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层
Slf4j
RestController
Validated
public class UserController{Resourceprivate UserService userService;GetMapping(/selectById)public UserVO selectById(NotNull Long userId){return userService.selectById(userId);}PostMapping(/add)public String add(RequestBody Validated UserAddReq addReq){userService.add(addReq.getUsername(),addReq.getPhone(),addReq.getfeatures());return ok;}
}
方法一ExtendWith(MockitoExtension.class)Mock等注解
ExtendWith(MockitoExtension.class)
public class InitMockSpyMethod1{mockprivate UserService mockUserService;Spyprivate UserService spyUserService;Testpublic void test1(){//true 判断某对象是不是mock对象System.out.println(Mockito.mockingDetails(mockUserService).isMock() Mockito.mockingDetails(mockUserService).isMock());//false 判断某对象是不是apy对象System.out.println(Mockito.mockingDetails(mockUserService).isMock() Mockito.mockingDetails(mockUserService).isMock());//true 判断某对象是不是spy对象System.out.println(Mockito.mockingDetails(spyUserService).isSpy() Mockito.mockingDetails(spyUserService).isSpy());//true 判断某对象是不是spy对象,因为spy是一种特殊的mockspy对象是另一种不同类型的mock对象System.out.println(Mockito.mockingDetails(spyUserService).isMock() Mockito.mockingDetail(spyUserService).isMock());}
}
spy对象是一种特殊的mock对象
方法二:Mockito.mock(X.class)等静态方法
public class InitMockSpyMethod1{private UserService mockUserService;private UserService spyUserService;BeforeEachpublic void init(){mockUserService Mockito.mock(UserService.class);spyUserService Mockito.spy(UserService.class);}Testpublic void test1(){System.out.println(Mockito.mockingDetails(mockUserService).isMock() Mockito.mockingDetails(mockUserService).isMock());System.out.println(Mockito.mockingDetails(mockUserService).isSpy() Mockito.mockingDetails(mockUserService).isSpy());System.out.println(Mockito.mockingDetails(spyUserService).isMock() Mockito.mockingDetails(spyUserService).isMock());}
}
方法三MockitoAnnotations.openMocks(this)Mock等注解
public class InitMockSpyMethod1{mockprivate UserService mockUserService;Spyprivate UserService spyUserService;BeforeEachpublic void init(){MockitoAnnotations.openMocks(this);}Testpublic void test1(){//true 判断某对象是不是mock对象System.out.println(Mockito.mockingDetails(mockUserService).isMock() Mockito.mockingDetails(mockUserService).isMock());//false 判断某对象是不是apy对象System.out.println(Mockito.mockingDetails(mockUserService).isMock() Mockito.mockingDetails(mockUserService).isMock());//true 判断某对象是不是spy对象System.out.println(Mockito.mockingDetails(spyUserService).isSpy() Mockito.mockingDetails(spyUserService).isSpy());//true 判断某对象是不是spy对象,因为spy是一种特殊的mockspy对象是另一种不同类型的mock对象System.out.println(Mockito.mockingDetails(spyUserService).isMock() Mockito.mockingDetail(spyUserService).isMock());}
}
五参数匹配
参数匹配指的是通过方法签名参数来指定哪些方法调用需要处理被处理插桩、verify验证
对于mock对象不会调用真实方法直接返回mock对象的默认值
默认值int、nullUserVO、空集合list 六方法插桩
指定调用某个方法时的行为stubbing达到相互隔离的目的 /**
*测试插桩时的参数匹配
*/
Test
public void test2(){UserUpdateReq userUpdateReq1 new UserUpdateReq();userUpdateReq1.setId(1L);userUpdateReq1.setPhone(1L);//指定参数为userUpdateReq1时调用mockUserService.modifyById(userUpdateReq1);Mockito.doReturn(99).when(mockUserService).modifyById(userUpdateReq1);int result1 mockUserService.modifyById(userUpdateReq1);//运行结果为99System.out.println(result1 result1);UserUpdateReq userUpdateReq2 new UserUpdateReq();userUpdateReq2.setId(2L);userUpdateReq2.setPhone(2L);int result2 mockUserService.modifyById(userUpdateReq2);//运行结果为0System.out.println(result2 result2);
}
总结
是告诉mockito当传入的是下面的参数这个类型时才对其进插桩若不是这个值则不用对它进行插桩 若想要拦截某种类型的任意对象则需要运用到
ArgumentMatchers.any拦截UserUpdateReq类型的任意对象 校验 add方法调用一次校验通过。 private UserService mockUserService;Testpublic void test4(){ListString features new ArrayList();mockUserService.add(实验,123,festures);//校验参数为乐之者,123,festuresfeatures的add方法调用了1次Mockito.verify(mockUserService,Mockito.times(2)).add(实验,123,festures)//报错 要么都用要么就都别用// Mockito.verify(mockUserService,Mockito.times(2)).add(实验,123,festures);//此时可以校验通过Mockito.verify(mockUserService,Mockito.times(2)).add(anyString(),anyString(),anyList());}}
但是有一点需要牢记的除了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标注的变量所对应的对象里面去。 注入的原理