当前位置: 首页 > 后端技术 > Java

Mockito

时间:2023-04-01 23:55:10 Java

,Java开发的模拟框架,在日常开发中,习惯性的写完需要的代码,嗖的跑一个main函数或者写几个简单的JUnit单元测试运行功能点,多写java训练一个单元测试可以毫无问题的上网(其实这个是不规范的)。对于需要对接第三方或者验证不同条件的代码分支逻辑,这种方式会变得不可取,因为业务逻辑需要依赖其他接口,而我们此时依赖的接口还没有准备好,那怎么办我们应该做什么?这时候,Mockito就派上用场了。一方面,使用Mockito可以屏蔽依赖的接口,返回Mock数据,让双方的开发可以同步(确定接口的协议)编码。另一方面,使用Mockito来验证业务逻辑。更改为部分代码可以返回测试用例,看看更改是否覆盖了所有测试点。因此,使用Mockito不仅可以保证代码的质量,还可以提高代码的可维护性,提前发现代码中的bug。Mock的四要素什么是Mock在软件开发的世界之外,“Mock”这个词的意思是模仿或效仿。所以,“Mock”可以理解为替身,替身。软件开发中提到“Mock”,通常理解为模拟对象或者为什么Fake需要Mock。Mock是为了解决单元之间耦合和代码分层开发的问题。测试的问题,所以模拟对象是单元测试的一部分Mock有什么好处提前创建测试,提高代码质量,TDD(测试驱动开发)并行工作创建验证或演示程序,为不可访问的资源编写测试什么是MockitoMockito是一个很好的模拟框架,你可以用它简洁的API写出漂亮的测试代码,它的测试代码可读性强并且会产生清晰的错误日志。1.导入依赖:org.mockitomockito-core3.3.3test注:Mockito3.X版本使用JDK8API,与2.X版本相比变化不大。2.在测试类中添加@RunWith注解,制作Runner类,即MockitoJUnitRunner@RunWith(MockitoJUnitRunner.class)publicclassMockitoDemoTest{//注入依赖的资源对象@MockprivateMockitoTestServicemockitoTestService;@Beforepublicvoidbefore(){MockitoAnnotations.initMocks(this);}}从代码中可以观察到@Mock标记的对象是Mocked,在初始化之前执行MockitoAnnotations.initMocks(this)告诉框架生成Mock相关注解生效.3.验证对象的行为Verify@TestpublicvoidtestVerify(){//创建一个mockListmockedList=mock(List.class);mockedList.add("1");mockedList.clear();//验证list调用了add操作行为verify(mockedList).add("1");//验证list调用了的操作行为clearverify(mockedList).clear();//使用内置的anyInt()参数匹配器和存根when(mockedList.get(anyInt())).thenReturn("element");System.out.println(mockedList.get(2));//这里的输出是elementverify(mockedList).get(anyInt());}4、stubbing——stubbingstubbing是完全模拟一个外部依赖来提供测试需要的测试数据@TestpublicvoidtestStub(){//可以模拟特定类,而不仅仅是接口LinkedListmockedList=mock(LinkedList.class);//Stub(stubbing)when(mockedList.get(0)).thenReturn("first");when(mockedList.get(1)).thenThrow(newRuntimeException());//下面会打印“first”System.out.println(mockedList.get(0));//下面会抛出运行时异常System.out.println(mockedList.get(1));//下面会打印“null”,因为get(999)没有存根(stub)System.out.println(mockedList.get(999));doThrow(newRuntimeException()).when(mockedList).clear();//下面会抛出RuntimeException:mockedList.clear();存根(stub)可以被覆盖:例如测试方法可以覆盖普通存根一旦完成存根方法将永远返回存根的值,无论此方法被调用多少次");mock.someMethod("somearg");//第一次调用:抛出运行时异常//第二次调用:print"foo"System.out.println(mock.someMethod("somearg"));//任何继续调用:仍然打印“foo”(最后存根生效)。System.out.println(mock.someMethod("somearg"));//延续存根的替代较短版本:when(mock.someMethod("somearg")).thenReturn("one","two","three");when(mock.someMethod(anyString())).thenAnswer(newAnswer(){Objectanswer(InvocationOnMockinvocation){Object[]args=invocation.getArguments();Objectmock=invocation.getMock();return"calledwitharguments:"+args;}});//"calledwith参数参数:fooSystem.out。println(mock.someMethod("foo"));}6.参数匹配器@TestpublicvoidtestArugument{//使用内置的anyInt()参数匹配器when(mockedList.get(anyInt())).thenReturn("element");System.out.println(mockedList.get(999));//打印“元素”//也可以用参数匹配器验证verify(mockedList).get(anyInt());//注意:如果使用参数匹配器,所有参数必须通过匹配器提供verify(mock).someMethod(anyInt(),anyString(),eq("thirdargument"));//上面是正确的——eq(0也是参数匹配器),下面是错误的verify(mock).someMethod(anyInt(),anyString(),"thirdargument");}7.验证准确的调用次数/至少X次/从不@TestpublicvoidtestVerify{ListmockedList=newArrayList();mockedList.add("一次");mockedList.add("两次");mockedList.add("两次");mockedList.add("三次");mockedList.add("三次");mockedList.add("threetimes"times");//下面两个验证是等价的——使用times(1)verify(mockedList).add("once");verify(mockedList,times(1)).add("once");默认验证(mockedList,times(2)).add("twice");verify(mockedList,times(3)).add("threetimes");//使用never()验证。never()等价于次(0)verify(mockedList,never()).add("neverhappened");//使用atLeast()/atMost()来验证verify(mockedList,atLeastOnce()).add("三次");验证(mockedList,atLeast(2)).add("五次");验证(mockedList,atMost(5)).add("三次");}8.验证调用顺序@TestpublicvoidtestOrder(){//A.SingleMock,方法必须按照特定顺序调用ListsingleMock=mock(List.class);//使用单MocksingleMock.add("被先添加");singleMock.add("wasaddedsecond");//为singleMock创建inOrder检查器InOrderinOrder=inOrder(singleMock);//确保add方法先被“wasaddedfirst”调用,然后被“wasaddedsecond”调用inOrder.verify(singleMock).add("先被添加");inOrder.verify(singleMock).add("被第二个添加");}来源作者:GoQeng