马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一:单元测试的特点
- 共同断言利用(可以杜绝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层:
- @Slf4j
- @RestController
- @Validated
- public class UserController{
- @Resource
- private 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{
- @mock
- private UserService mockUserService;
- @Spy
- private UserService spyUserService;
- @Test
- public 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是一种特殊的mock(spy对象是另一种不同类型的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;
- @BeforeEach
- public void init(){
- mockUserService = Mockito.mock(UserService.class);
- spyUserService = Mockito.spy(UserService.class);
- }
-
- @Test
- public 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{
- @mock
- private UserService mockUserService;
- @Spy
- private UserService spyUserService;
- @BeforeEach
- public void init(){
- MockitoAnnotations.openMocks(this);
- }
-
- @Test
- public 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是一种特殊的mock(spy对象是另一种不同类型的mock对象)
- System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetail(spyUserService).isMock());
- }
- }
复制代码 五:参数匹配
参数匹配指的是:通过方法署名(参数)来指定哪些方法调用必要处置惩罚被处置惩罚(插桩、verify验证)
对于mock对象不会调用真实方法,直接返回mock对象的默认值;
默认值(int)、null(UserVO)、空聚集(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);
- //运行结果为99
- System.out.println("result1 = " + result1);
-
- UserUpdateReq userUpdateReq2 = new UserUpdateReq();
- userUpdateReq2.setId(2L);
- userUpdateReq2.setPhone("2L");
- int result2 = mockUserService.modifyById(userUpdateReq2);
- //运行结果为0
- System.out.println("result2 = " + result2);
- }
复制代码 总结:
是告诉mockito当传入的是下面的参数这个范例时,才对其进插桩,若不是这个值,则不消对它举行插桩
若想要拦截某种范例的恣意对象,则必要运用到:
ArgumentMatchers.any拦截UserUpdateReq范例的恣意对象
校验:
add方法调用一次,校验通过。
- private UserService mockUserService;
- @Test
- public void test4(){
- List<String> features = new ArrayList<>();
- mockUserService.add("实验","123",festures);
- //校验参数为"乐之者","123",festures,features的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标注的变量所对应的对象内里去。
注入的原理:
|