最新要闻
- 别乱买!三大要素教你如何选对吸尘器
- 环球看点!一次看个够!《原子之心》双子舞伶所有场景合集
- 世界时讯:微软为Chrome官网注入大幅广告:只为将用户留在Edge
- 天天热资讯!微软收购动视暴雪获新盟友!NVIDIA态度转变签署10年游戏协议
- 每日播报!若若_关于若若的简介
- 焦点速读:长沙凌晨1点马路人流量惊人 像在倒时差:网友称想去打卡 当地人回应
- 全球最资讯丨8GB来了!iPhone 15内存大升级:苹果区别对待 想要花万元买Pro版
- 环球热头条丨荣耀Magic5 Lite获DXO电池性能第一名 续航可超三天
- 雷克萨斯、英菲尼迪、凯迪拉克等豪车中国市场暴跌:国人不当冤大头
- 热文:OPPO打造!唯一配备潜望长焦的天玑旗舰来了
- 天天短讯!死磕RTX 40!AMD RX 7600/7700/7800齐曝光:据说苏妈定价有诚意
- 重现《放羊的星星》!林志颖特斯拉车祸后复出晒照 事故原因成谜 是踩错刹车?
- 天天百事通!今日成都到康定怎么坐车_成都到康定
- 亮机卡也有春天 锐龙7000核显超频到3.1GHz 游戏性能猛增40%
- 当前要闻:困扰十几亿人!脚趾甲咋会向肉里长?
- 世界焦点!TCL发布超薄四开门冰箱T9:0cm无缝式嵌入 456L仅3399元
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
【码农教程】手把手教你学会Mockito使用
作者:京东零售 秦浩然
(资料图)
一、前期准备~
1、准备工作
org.mockito mockito-core 2.7.19 test junit junit 4.12 test
2、入门知识
1)Mockito:简单轻量级的做mocking测试的框架;2)mock对象:在调试期间用来作为真实对象的替代品;3)mock测试:在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试;4)stub:打桩,就是为mock对象的方法指定返回值(可抛出异常);5)verify:行为验证,验证指定方法调用情况(是否被调用,调用次数等);
3、五分钟入门Demo
@Testpublic void test0() { //1、创建mock对象(模拟依赖的对象) final List mock = Mockito.mock(List.class); //2、使用mock对象(mock对象会对接口或类的方法给出默认实现) System.out.println("mock.add result => " + mock.add("first")); //false System.out.println("mock.size result => " + mock.size()); //0 //3、打桩操作(状态测试:设置该对象指定方法被调用时的返回值) Mockito.when(mock.get(0)).thenReturn("second"); Mockito.doReturn(66).when(mock).size(); //3、使用mock对象的stub(测试打桩结果) System.out.println("mock.get result => " + mock.get(0)); //second System.out.println("mock.size result => " + mock.size()); //66 //4、验证交互 verification(行为测试:验证方法调用情况) Mockito.verify(mock).get(Mockito.anyInt()); Mockito.verify(mock, Mockito.times(2)).size(); //5、验证返回的结果(这是JUnit的功能) assertEquals("second", mock.get(0)); assertEquals(66, mock.size());}
二、让我们开始学习吧!
1、行为验证
• 一旦mock对象被创建了,mock对象会记住所有的交互,然后你就可以选择性的验证你感兴趣的交互,验证不通过则抛出异常。
@Testpublic void test1() { final List mockList = Mockito.mock(List.class); mockList.add("mock1"); mockList.get(0); mockList.size(); mockList.clear(); // 验证方法被使用(默认1次) Mockito.verify(mockList).add("mock1"); // 验证方法被使用1次 Mockito.verify(mockList, Mockito.times(1)).get(0); // 验证方法至少被使用1次 Mockito.verify(mockList, Mockito.atLeast(1)).size(); // 验证方法没有被使用 Mockito.verify(mockList, Mockito.never()).contains("mock2"); // 验证方法至多被使用5次 Mockito.verify(mockList, Mockito.atMost(5)).clear(); // 指定方法调用超时时间 Mockito.verify(mockList, timeout(100)).get(0); // 指定时间内需要完成的次数 Mockito.verify(mockList, timeout(200).atLeastOnce()).size();}
2、如何做一些测试桩stub
• 默认情况下,所有的函数都有返回值。mock函数默认返回的是null,一个空的集合或者一个被对象类型包装的内置类型,例如0、false对应的对象类型为Integer、Boolean;
• 一旦测试桩函数被调用,该函数将会一致返回固定的值;
• 对于 static 和 final 方法, Mockito 无法对其 when(…).thenReturn(…) 操作。
@Testpublic void test2() { //静态导入,减少代码量:import static org.mockito.Mockito.*; final ArrayList mockList = mock(ArrayList.class); // 设置方法调用返回值 when(mockList.add("test2")).thenReturn(true); doReturn(true).when(mockList).add("test2"); System.out.println(mockList.add("test2")); //true // 设置方法调用抛出异常 when(mockList.get(0)).thenThrow(new RuntimeException()); doThrow(new RuntimeException()).when(mockList).get(0); System.out.println(mockList.get(0)); //throw RuntimeException // 无返回方法打桩 doNothing().when(mockList).clear(); // 为回调做测试桩(对方法返回进行拦截处理) final Answer answer = new Answer() { @Override public String answer(InvocationOnMock invocationOnMock) throws Throwable { final List mock = (List) invocationOnMock.getMock(); return "mock.size result => " + mock.size(); } }; when(mockList.get(1)).thenAnswer(answer); doAnswer(answer).when(mockList).get(1); System.out.println(mockList.get(1)); //mock.size result => 0 // 对同一方法多次打桩,以最后一次为准 when(mockList.get(2)).thenReturn("test2_1"); when(mockList.get(2)).thenReturn("test2_2"); System.out.println(mockList.get(2)); //test2_2 System.out.println(mockList.get(2)); //test2_2 // 设置多次调用同类型结果 when(mockList.get(3)).thenReturn("test2_1", "test2_2"); when(mockList.get(3)).thenReturn("test2_1").thenReturn("test2_2"); System.out.println(mockList.get(3)); //test2_1 System.out.println(mockList.get(3)); //test2_2 // 为连续调用做测试桩(为同一个函数调用的不同的返回值或异常做测试桩) when(mockList.get(4)).thenReturn("test2").thenThrow(new RuntimeException()); doReturn("test2").doThrow(new RuntimeException()).when(mockList).get(4); System.out.println(mockList.get(4)); //test2 System.out.println(mockList.get(4)); //throw RuntimeException // 无打桩方法,返回默认值 System.out.println(mockList.get(99)); //null}
3、参数匹配器
• 参数匹配器使验证和测试桩变得更灵活;
• 为了合理的使用复杂的参数匹配,使用equals()与anyX() 的匹配器会使得测试代码更简洁、简单。有时,会迫使你重构代码以使用equals()匹配或者实现equals()函数来帮助你进行测试;
• 如果你使用参数匹配器,所有参数都必须由匹配器提供;
• 支持自定义参数匹配器;
@Testpublic void test3() { final Map mockMap = mock(Map.class); // 正常打桩测试 when(mockMap.get("key")).thenReturn("value1"); System.out.println(mockMap.get("key")); //value1 // 为灵活起见,可使用参数匹配器 when(mockMap.get(anyString())).thenReturn("value2"); System.out.println(mockMap.get(anyString())); //value2 System.out.println(mockMap.get("test_key")); //value2 System.out.println(mockMap.get(0)); //null // 多个入参时,要么都使用参数匹配器,要么都不使用,否则会异常 when(mockMap.put(anyString(), anyInt())).thenReturn("value3"); System.out.println(mockMap.put("key3", 3)); //value3 System.out.println(mockMap.put(anyString(), anyInt())); //value3 System.out.println(mockMap.put("key3", anyInt())); //异常 // 行为验证时,也支持使用参数匹配器 verify(mockMap, atLeastOnce()).get(anyString()); verify(mockMap).put(anyString(), eq(3)); // 自定义参数匹配器 final ArgumentMatcher myArgumentMatcher = new ArgumentMatcher() { @Override public boolean matches(ArgumentTestRequest request) { return "name".equals(request.getName()) || "value".equals(request.getValue()); } }; // 自定义参数匹配器使用 final ArgumentTestService mock = mock(ArgumentTestService.class); when(mock.argumentTestMethod(argThat(myArgumentMatcher))).thenReturn("success"); doReturn("success").when(mock).argumentTestMethod(argThat(myArgumentMatcher)); System.out.println(mock.argumentTestMethod(new ArgumentTestRequest("name", "value"))); // success System.out.println(mock.argumentTestMethod(new ArgumentTestRequest())); //null}
4、执行顺序验证
• 验证执行顺序是非常灵活的-你不需要一个一个的验证所有交互,只需要验证你感兴趣的对象即可;
• 你可以仅通过那些需要验证顺序的mock对象来创建InOrder对象;
@Testpublic void test4() { // 验证同一个对象多个方法的执行顺序 final List mockList = mock(List.class); mockList.add("first"); mockList.add("second"); final InOrder inOrder = inOrder(mockList); inOrder.verify(mockList).add("first"); inOrder.verify(mockList).add("second"); // 验证多个对象多个方法的执行顺序 final List mockList1 = mock(List.class); final List mockList2 = mock(List.class); mockList1.get(0); mockList1.get(1); mockList2.get(0); mockList1.get(2); mockList2.get(1); final InOrder inOrder1 = inOrder(mockList1, mockList2); inOrder1.verify(mockList1).get(0); inOrder1.verify(mockList1).get(2); inOrder1.verify(mockList2).get(1);}
5、确保交互(interaction)操作不会执行在mock对象上
• 一些用户可能会在频繁地使用verifyNoMoreInteractions(),甚至在每个测试函数中都用。但是verifyNoMoreInteractions()并不建议在每个测试函数中都使用;
• verifyNoMoreInteractions()在交互测试套件中只是一个便利的验证,它的作用是当你需要验证是否存在冗余调用时;
@Testpublic void test5() { // 验证某个交互是否从未被执行 final List mock = mock(List.class); mock.add("first"); verify(mock, never()).add("test5"); //通过 verify(mock, never()).add("first"); //异常 // 验证mock对象没有交互过 final List mock1 = mock(List.class); final List mock2 = mock(List.class); verifyZeroInteractions(mock1); //通过 verifyNoMoreInteractions(mock1, mock2); //通过 verifyZeroInteractions(mock, mock2); //异常 // 注意:可能只想验证前面的逻辑,但是加上最后一行,会导致出现异常。建议使用方法层面的验证,如:never(); // 在验证是否有冗余调用的时候,可使用此种方式。如下: final List mockList = mock(List.class); mockList.add("one"); mockList.add("two"); verify(mockList).add("one"); // 通过 verify(mockList, never()).get(0); //通过 verifyZeroInteractions(mockList); //异常}
6、使用注解简化mock对象创建
注意!下面这句代码需要在运行测试函数之前被调用,一般放到测试类的基类或者test runner中:
MockitoAnnotations.initMocks(this);
也可以使用内置的runner: MockitoJUnitRunner 或者一个rule : MockitoRule;
// 代替 mock(ArgumentTestService.class) 创建mock对象;@Mockprivate ArgumentTestService argumentTestService;// 若改注解修饰的对象有成员变量,@Mock定义的mock对象会被自动注入;@InjectMocksprivate MockitoAnnotationServiceImpl mockitoAnnotationService;@Testpublic void test6() { // 注意!下面这句代码需要在运行测试函数之前被调用,一般放到测试类的基类或者test runner中; MockitoAnnotations.initMocks(this); when(argumentTestService.argumentTestMethod(new ArgumentTestRequest())).thenReturn("success"); System.out.println(argumentTestService.argumentTestMethod(new ArgumentTestRequest())); //success System.out.println(mockitoAnnotationService.mockitoAnnotationTestMethod()); //null}
7、监控真实对象(部分mock)
• 可以为真实对象创建一个监控(spy)对象。当你使用这个spy对象时真实的对象也会也调用,除非它的函数被stub了;
• 尽量少使用spy对象,使用时也需要小心形式,例如spy对象可以用来处理遗留代码;
• stub语法中同样提供了部分mock的方法,可以调用真实的方法;
完全mock:
上文讲的内容是完全mock,即创建的mock对象与真实对象无关,mock对象的方法默认都是基本的实现,返回基本类型。可基于接口、实现类创建mock对象。
部分mock:
所谓部分mock,即创建的mock对象时基于真实对象的,mock对象的方法都是默认使用真实对象的方法,除非stub之后,才会以stub为准。基于实现类创建mock对象,否则在没有stub的情况下,调用真实方法时,会出现异常。
注意点:
Mockito并不会为真实对象代理函数调用,实际上它会拷贝真实对象。因此如果你保留了真实对象并且与之交互,不要期望从监控对象得到正确的结果。 当你在监控对象上调用一个没有被stub的函数时并不会调用真实对象的对应函数,你不会在真实对象上看到任何效果
@Testpublic void test7() { // stub部分mock(stub中使用真实调用)。注意:需要mock实现类,否则会有异常 final StubTestService stubTestService = mock(StubTestServiceImpl.class); when(stubTestService.stubTestMethodA("paramA")).thenCallRealMethod(); doCallRealMethod().when(stubTestService).stubTestMethodB(); System.out.println(stubTestService.stubTestMethodA("paramA")); //stubTestMethodA is called, param = paramA System.out.println(stubTestService.stubTestMethodB()); //stubTestMethodB is called System.out.println(stubTestService.stubTestMethodC()); //null // spy部分mock final LinkedList linkedList = new LinkedList(); final LinkedList spy = spy(linkedList); spy.add("one"); spy.add("two"); doReturn(100).when(spy).size(); when(spy.get(0)).thenReturn("one_test"); System.out.println(spy.size()); //100 System.out.println(spy.get(0)); //one_test System.out.println(spy.get(1)); //two // spy可以类比AOP。在spy中,由于默认是调用真实方法,所以第二种写法不等价于第一种写法,不推荐这种写法。 doReturn("two_test").when(spy).get(2); when(spy.get(2)).thenReturn("two_test"); //异常 java.lang.IndexOutOfBoundsException: Index: 2, Size: 2 System.out.println(spy.get(2)); //two_test // spy对象只是真实对象的复制,真实对象的改变不会影响spy对象 final List arrayList = new ArrayList<>(); final List spy1 = spy(arrayList); spy1.add(0, "one"); System.out.println(spy1.get(0)); //one arrayList.add(0, "list1"); System.out.println(arrayList.get(0)); //list1 System.out.println(spy1.get(0)); //one // 若对某个方法stub之后,又想调用真实的方法,可以使用reset(spy) final ArrayList arrayList1 = new ArrayList<>(); final ArrayList spy2 = spy(arrayList1); doReturn(100).when(spy2).size(); System.out.println(spy2.size()); //100 reset(spy2); System.out.println(spy2.size()); //0}
8、@Mock 和 @Spy的使用
• @Mock 等价于 Mockito.mock(Object.class);
• @Spy 等价于 Mockito.spy(obj);
区分是mock对象还是spy对象:Mockito.mockingDetails(someObject).isMock();Mockito.mockingDetails(someObject).isSpy();@Mockprivate StubTestService stubTestService;@Spyprivate StubTestServiceImpl stubTestServiceImpl;@Spyprivate StubTestService stubTestServiceImpl1 = new StubTestServiceImpl();@Testpublic void test8() { MockitoAnnotations.initMocks(this); // mock对象返回默认 System.out.println(stubTestService.stubTestMethodB()); //null // spy对象调用真实方法 System.out.println(stubTestServiceImpl.stubTestMethodC()); //stubTestMethodC is called System.out.println(stubTestServiceImpl1.stubTestMethodA("spy")); //stubTestMethodA is called, param = spy // 区分是mock对象还是spy对象 System.out.println(mockingDetails(stubTestService).isMock()); //true System.out.println(mockingDetails(stubTestService).isSpy()); //false System.out.println(mockingDetails(stubTestServiceImpl).isSpy()); //true}
9、ArgumentCaptor(参数捕获器)捕获方法参数进行验证。(可代替参数匹配器使用)
• 在某些场景中,不光要对方法的返回值和调用进行验证,同时需要验证一系列交互后所传入方法的参数。那么我们可以用参数捕获器来捕获传入方法的参数进行验证,看它是否符合我们的要求。
ArgumentCaptor介绍
通过ArgumentCaptor对象的forClass(Class
ArgumentCaptor的Api
argument.capture() 捕获方法参数
argument.getValue() 获取方法参数值,如果方法进行了多次调用,它将返回最后一个参数值
argument.getAllValues() 方法进行多次调用后,返回多个参数值
@Testpublic void test9() { List mock = mock(List.class); List mock1 = mock(List.class); mock.add("John"); mock1.add("Brian"); mock1.add("Jim"); // 获取方法参数 ArgumentCaptor argument = ArgumentCaptor.forClass(String.class); verify(mock).add(argument.capture()); System.out.println(argument.getValue()); //John // 多次调用获取最后一次 ArgumentCaptor argument1 = ArgumentCaptor.forClass(String.class); verify(mock1, times(2)).add(argument1.capture()); System.out.println(argument1.getValue()); //Jim // 获取所有调用参数 System.out.println(argument1.getAllValues()); //[Brian, Jim]}
10、简化 ArgumentCaptor 的创建
@Mockprivate List captorList;@Captorprivate ArgumentCaptor argumentCaptor;@Testpublic void test10() { MockitoAnnotations.initMocks(this); captorList.add("cap1"); captorList.add("cap2"); System.out.println(captorList.size()); verify(captorList, atLeastOnce()).add(argumentCaptor.capture()); System.out.println(argumentCaptor.getAllValues());}
11、高级特性:自定义验证失败信息
@Testpublic void test11() { final ArrayList arrayList = mock(ArrayList.class); arrayList.add("one"); arrayList.add("two"); verify(arrayList, description("size()没有调用")).size(); // org.mockito.exceptions.base.MockitoAssertionError: size()没有调用 verify(arrayList, timeout(200).times(3).description("验证失败")).add(anyString()); //org.mockito.exceptions.base.MockitoAssertionError: 验证失败}
12、高级特性:修改没有测试桩的调用的默认返回值
• 可以指定策略来创建mock对象的返回值。这是一个高级特性,通常来说,你不需要写这样的测试;
• 它对于遗留系统来说是很有用处的。当你不需要为函数调用打桩时你可以指定一个默认的answer;
@Testpublic void test12(){ // 创建mock对象、使用默认返回 final ArrayList mockList = mock(ArrayList.class); System.out.println(mockList.get(0)); //null // 这个实现首先尝试全局配置,如果没有全局配置就会使用默认的回答,它返回0,空集合,null,等等。 // 参考返回配置:ReturnsEmptyValues mock(ArrayList.class, Answers.RETURNS_DEFAULTS); // ReturnsSmartNulls首先尝试返回普通值(0,空集合,空字符串,等等)然后它试图返回SmartNull。 // 如果最终返回对象,那么会简单返回null。一般用在处理遗留代码。 // 参考返回配置:ReturnsMoreEmptyValues mock(ArrayList.class, Answers.RETURNS_SMART_NULLS); // 未stub的方法,会调用真实方法。 // 注1:存根部分模拟使用时(mock.getSomething ()) .thenReturn (fakeValue)语法将调用的方法。对于部分模拟推荐使用doReturn语法。 // 注2:如果模拟是序列化反序列化,那么这个Answer将无法理解泛型的元数据。 mock(ArrayList.class, Answers.CALLS_REAL_METHODS); // 深度stub,用于嵌套对象的mock。参考:https://www.cnblogs.com/Ming8006/p/6297333.html mock(ArrayList.class, Answers.RETURNS_DEEP_STUBS); // ReturnsMocks首先尝试返回普通值(0,空集合,空字符串,等等)然后它试图返回mock。 // 如果返回类型不能mocked(例如是final)然后返回null。 mock(ArrayList.class, Answers.RETURNS_MOCKS); // mock对象的方法调用后,可以返回自己(类似builder模式) mock(ArrayList.class, Answers.RETURNS_SELF); // 自定义返回 final Answer answer = new Answer() { @Override public String answer(InvocationOnMock invocation) throws Throwable { return "test_answer"; } }; final ArrayList mockList1 = mock(ArrayList.class, answer); System.out.println(mockList1.get(0)); //test_answer}
三、学习了这么多,牛刀小试一下!
测试实体类
@Datapublic class User { /** * 姓名,登录密码 */
持久层DAO
public interface UserDao { /** * 根据name查找user * @param name * @return */ User getUserByName(String name); /** * 保存user * @param user * @return */ Integer saveUser(User user);}
业务层Service接口
public interface UserService { /** * 根据name查找user * @param name * @return */ User getUserByName(String name); /** * 保存user * @param user * @return */ Integer saveUser(User user);}
业务层Serive实现类
@Servicepublic class UserServiceImpl implements UserService { //userDao @Autowired private UserDao userDao; /** * 根据name查找user * @param name * @return */ @Override public User getUserByName(String name) { try { return userDao.getUserByName(name); } catch (Exception e) { throw new RuntimeException("查询user异常"); } } /** * 保存user * @param user * @return */ @Override public Integer saveUser(User user) { if (userDao.getUserByName(user.getName()) != null) { throw new RuntimeException("用户名已存在"); } try { return userDao.saveUser(user); } catch (Exception e) { throw new RuntimeException("保存用户异常"); } }}
现在我们的Service写好了,想要单元测试一下,但是Dao是其他人开发的,目前还没有写好,那我们如何测试呢?
public class UserServiceTest { /** * Mock测试:根据name查询user */ @Test public void getUserByNameTest() { // mock对象 final UserDao userDao = mock(UserDao.class); final UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(userDao); // stub调用 final User user = new User(); user.setName("admin"); user.setPassword("pass"); when(userDao.getUserByName("admin")).thenReturn(user); // 执行待测试方法 final User user1 = userService.getUserByName("admin"); System.out.println("查询结果:" + JacksonUtil.obj2json(user1)); //查询结果:{"name":"admin","password":"pass"} // 验证mock对象交互 verify(userDao).getUserByName(anyString()); // 验证查询结果 Assert.assertNotNull("查询结果为空!", user1); Assert.assertEquals("查询结果错误!", "admin", user1.getName()); } /** * Mock测试:保存user */ @Mock private UserDao userDao; @InjectMocks private UserServiceImpl userService; @Test public void saveUserTest() throws Exception{ // 执行注解初始化 MockitoAnnotations.initMocks(this); // mock对象stub操作 final User user = new User(); user.setName("admin"); user.setPassword("pass"); when(userDao.getUserByName("admin")).thenReturn(user).thenReturn(null); when(userDao.saveUser(any(User.class))).thenReturn(1); // 验证用户名重复的情况 try { userService.saveUser(user); throw new Exception(); //走到这里说明验证失败 } catch (RuntimeException e) { System.out.println("重复用户名保存失败-测试通过"); //重复用户名保存失败-测试通过 } verify(userDao).getUserByName("admin"); // 验证正常保存的情况 user.setName("user"); final Integer integer = userService.saveUser(user); System.out.println("保存结果:" + integer); //保存结果:1 Assert.assertEquals("保存失败!", 1, integer.longValue()); verify(userDao).saveUser(any(User.class)); verify(userDao, times(2)).getUserByName(anyString()); }}
根据以上代码我们可以知道,当我们的待测类开发完成而依赖的类的实现还没有开发完成。此时,我们就可以用到我们的Mock测试,模拟我们依赖类的返回值,使我们的待测类与依赖类解耦。这样,我们就可以对我们的待测类进行单元测了。
四、参考文档及进一步学习~
Mockito英文版javadoc:https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/Mockito.htmlMockito中文文档(部分):https://blog.csdn.net/bboyfeiyu/article/details/52127551#35Mockito使用教程:https://www.cnblogs.com/Ming8006/p/6297333.html参数捕获器使用:https://www.journaldev.com/21892/mockito-argumentcaptor-captor-annotation利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证:https://www.iteye.com/blog/hotdog-916364改变mock返回值:https://www.huangyunkun.com/2014/10/25/mockito-deep-stub-with-enum/五分钟了解Mockito:https://www.iteye.com/blog/liuzhijun-1512780使用Mockito进行单元测试:https://www.iteye.com/blog/qiuguo0205-1443344JUnit + Mockito 单元测试:https://blog.csdn.net/zhangxin09/article/details/42422643Mockito中@Mock与@InjectMock:https://www.cnblogs.com/langren1992/p/9681600.htmlmockito中两种部分mock的实现,spy、callRealMethod:https://www.cnblogs.com/softidea/p/4204389.htmlMockito 中被 Mocked 的对象属性及方法的默认值:https://www.cnblogs.com/fnlingnzb-learner/p/10635250.html单元测试工具之Mockito:https://blog.csdn.net/qq_32140971/article/details/90598454引入Mockito测试用@Spy和@Mock:https://blog.csdn.net/message_lx/article/details/83308114Mockito初探(含实例):https://www.iteye.com/blog/sgq0085-2031319测试覆盖率统计:https://blog.csdn.net/lvyuan1234/article/details/82836052?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task测试覆盖率无法统计解决:https://blog.csdn.net/zhanglei082319/article/details/81536398
-
世界播报:2.概率论
2 概率论2 1前沿Probabilitytheoryisnothingbutcommonsensereducedtocalculation ——PierreLaplac
来源: 【码农教程】手把手教你学会Mockito使用
世界热门:用一个例子学会适配器设计模式
天天视点!量化工具篇
世界播报:2.概率论
视焦点讯!(数据库系统概论|王珊)第六章关系数据理论-第二节:规范化
别乱买!三大要素教你如何选对吸尘器
环球看点!一次看个够!《原子之心》双子舞伶所有场景合集
世界时讯:微软为Chrome官网注入大幅广告:只为将用户留在Edge
天天热资讯!微软收购动视暴雪获新盟友!NVIDIA态度转变签署10年游戏协议
热门:读Java实战(第二版)笔记17_反应式编程
每日播报!若若_关于若若的简介
焦点速读:长沙凌晨1点马路人流量惊人 像在倒时差:网友称想去打卡 当地人回应
全球最资讯丨8GB来了!iPhone 15内存大升级:苹果区别对待 想要花万元买Pro版
环球热头条丨荣耀Magic5 Lite获DXO电池性能第一名 续航可超三天
雷克萨斯、英菲尼迪、凯迪拉克等豪车中国市场暴跌:国人不当冤大头
今日聚焦!面试官:怎么去除 List 中的重复元素?我一行代码搞定,赶紧拿去用!
热文:OPPO打造!唯一配备潜望长焦的天玑旗舰来了
天天短讯!死磕RTX 40!AMD RX 7600/7700/7800齐曝光:据说苏妈定价有诚意
重现《放羊的星星》!林志颖特斯拉车祸后复出晒照 事故原因成谜 是踩错刹车?
Map数据结构详解
环球视讯!在PHP和JavaScript中设置Cookie、会话存储(SessionStorage)和本地存储(LocalStorage)
天天百事通!今日成都到康定怎么坐车_成都到康定
亮机卡也有春天 锐龙7000核显超频到3.1GHz 游戏性能猛增40%
当前要闻:困扰十几亿人!脚趾甲咋会向肉里长?
世界焦点!TCL发布超薄四开门冰箱T9:0cm无缝式嵌入 456L仅3399元
增程、换电、800V高压快充 谁才是未来新能源车最佳补能方式?
环球新动态:发3000元却收回2800元!“慈善主播”被行拘 账号被封
【焦点热闻】秘而不宣的读法
C#的string是一种糟糕的设计吗?
当前视讯!队列——queue的用法(及洛谷B3616)
vue-cli安装依赖 props属性三种方式 混入迷信 插件 elementUI vuex vue Routerd localStorage系列
openfoam文件读取
fusion app自定义事件源码介绍(上)
世界热门:RTX 4070 Laptop逆天能效比!七彩虹将星X15 AT 2023游戏本首发评测
全球快看:1月豪华车销量榜:蔚来碾压全系合资二线豪华品牌
被网友玩坏?微软Bing的ChatGPT被证实变愚蠢了
每日消息!“张伟”骗取数位宝马车主百万购车款 4S店疯狂推卸责任?
AMD锐龙7 7735HS迷你机也有“青春版”:只变了两个USB接口
环球今头条!攒台白色的MATX主机,在B760主板上也能玩好内存超频
全球焦点!RS485 MODBUS转PROFINET网关案例 | 超声波明渠流量计接入到PLC1200 PROFINE
焦点热门:前后端分离项目解决跨域的终极方法
环球今热点:[Java基础]自动装箱与自动拆箱--为什么整型比较必须用equals?
【天天新要闻】Detecting glass in Simulataneous Localisation and Mapping
天天热文:贝叶斯与卡尔曼滤波(2)--连续随机变量的贝叶斯公式
当前热门:用送的那块布擦镜片:小心眼镜被废!
观热点:60岁快递员意外猝死 快递公司回应:深感痛心 善后已达成一致
女子连刷10个差评商家找上门:不好吃你天天来干嘛 谁生活容易啊
【世界报资讯】果粉入手一加Ace 2:开20个应用不杀后台 苹果开3个应用就不行了
80后回忆的“均瑶牛奶”公司进军新能源车:首款纯电SUV云兔来了 莆田生产
信息:Qt调用摄像头一,基础版
k8s多节点二进制部署以及Dashboard UI
记住这12个要点,你也能打造出让HR和技术主管前一亮的前端简历
《原子之心》冰箱诺拉全九国语言配音:怎么没日语?
粉丝发现周深自用手机是iQOO 11 Pro传奇版:5米开外就能看到
电动两轮车总是骑半路就没电?这5种错误充电习惯赶快纠正
世界今头条!男子酷爱嚼槟榔:最终确诊舌癌
【报资讯】免费的ChatGPT意外断网 国内伪装自主的AI露馅了
守护安全|AIRIOT城市天然气综合管理解决方案
0x03_My-OS在实体机上面运行
每日播报!【算法训练营day53】LeetCode1143. 最长公共子序列 LeetCode1035. 不相交的线 LeetCode53. 最大子序和
快讯:两数之和、三数之和、四数之和(双指针)
世界焦点!今日山水一程三生有幸是形容爱情的吗_山水一程三生有幸
环球最资讯丨俞敏洪说想给董宇辉在北京买套房子 这话我听着耳熟
消息!魅族20未发先火!1元超前预订7小时订单破10万
世界热讯:研究称果糖或能导致老年痴呆:专家建议少食用
全球热议:旅日大熊猫香香坐顺丰飞机到家!1个月后与公众见面
环球视讯!成都一公司面试需填芝麻信用分 网友热议
每日信息:100亿级订单怎么调度,来一个大厂的极品方案
[学习笔记]Rocket.Chat业务数据备份
记录--uni-app实现京东canvas拍照识图功能
世界快资讯:Java+Jquer实现趋势图
全球最新:温州特斯拉事故20年驾龄司机仍昏迷:特斯拉回应称难过 重申全力配合调查
环球今热点:Xbox游戏将登陆任天堂主机 网友质疑:NS能带动吗?
世界微资讯!场面爆笑!外国人为开比亚迪开始学中文:难为“小迪”了
即时看!音悦台将回归登热搜!主体公司已成老赖:累计被执行1376万
世界视讯!什么是经营贷什么是消费贷?浅谈二者区别
puppet安装使用踩坑笔记
箭头函数详解
TypeScript 入门自学笔记 — 接口的使用(六)
快资讯丨Python关于异常处理的教程
天天观察:scrollView 嵌套 recyclerview 时 BaseQuickAdapter 九宫格图片拖拽到底部删除
14年老牌网站 音悦台要回归了!官方称很快就要内测
每日快看:杭州发现鱼类新物种苕溪鱲:通体散发宝蓝色金属光泽
当前播报:爱奇艺认错 恢复会员投屏!上海消保委:愿意为消费者叫板
是懂玩家的!《原子之心》为机器人姐妹花开通ins账号
焦点观察:张小泉公开一防菜刀断裂专利 这次拍蒜不断了?
当前最新:中小企业如何有效应对计算资源的弹性变化需求?
热消息:来一波骚操作,Java内存模型
全球新消息丨Windows家庭版安装本地组策略编辑器【gpedit.msc】
Redis详解
当前焦点!@ResponseBody注解的作用
万马股份(002276.SZ):万马新能源充电桩的枪线已经自产 由万马专缆生产
精选!售10-20万元 蔚来整合猎豹工厂:新品牌“萤火虫”落户安徽
今日最新!冲刺IPO!一年狂赚7亿美元 中国跨境电商神话靠啥吸粉?
乐视被强制执行100万:没版权擅自转播了优酷综艺
男子网购iPhone 14开箱发现是iQOO 商家赔50元优惠券被拒
当前动态:曾致135人死亡 印度断桥事故调查报告出炉:钢索严重腐蚀
0x02_My-OS操作系统里的helloworld
天天新资讯:iptables防火墙
世界热议:万物皆可集成资源包!低代码集成系列一网打尽