0


Java测试-mockito学习

目录

1 Mockito

mockito是Java中用于单元测试的模拟框架,Mockito库支持模拟创建、验证和存根。

通常和Junit框架组合完成对项目的单元测试。

2 各种模拟使用

2.1 mock接口并验证

测试demo-1:

//1--mock一些接口, 使用verify验证某些行为是否发生仅过一次@TestvoidmockListTest(){List listMock =mock(List.class);
        listMock.add("one");
        listMock.get(1);
        listMock.clear();verify(listMock).add("one");verify(listMock).clear();verify(listMock).get(1);}
mock

接口,并可

verify

行为是否发生过和已经发生次数。

2.2 mock具体类,并进行stub

测试demo-2:

//2--mock一些具体的类,并进行stub@TestvoidmockConcreteList(){LinkedList mockLinkedList =mock(LinkedList.class);when(mockLinkedList.get(0)).thenReturn("first");when(mockLinkedList.get(1)).thenThrow(newRuntimeException());System.out.println(mockLinkedList.get(0));//        System.out.println(mockLinkedList.get(1));System.out.println(mockLinkedList.get(999));}
mock

具体类,

stub

具体的行为返回值。

2.3 参数匹配器-Argument matchers

测试demo-3:

@TestvoidmockArgumentMatcherTest(){LinkedList mockLinkedList =mock(LinkedList.class);when(mockLinkedList.get(anyInt())).thenReturn("element");System.out.println(mockLinkedList.get(Integer.MAX_VALUE));//可以传入lambda表达式when(mockLinkedList.contains(argThat((str)->{String strNew =(String) str;return strNew.length()>5;}))).thenReturn(true);System.out.println(mockLinkedList.contains("cece"));System.out.println(mockLinkedList.contains("cecece"));verify(mockLinkedList).get(anyInt());}

运行结果:
在这里插入图片描述
可以使用内建的

anyInt

……系列或者自定义

argThat

,来完成stub需求,支持lambda表达式

2.4 验证实际调用的次数

测试demo-4:

@TestvoidverifyExactNumberTest(){LinkedList mockLinkedList =mock(LinkedList.class);
        mockLinkedList.add("one");

        mockLinkedList.add("two");
        mockLinkedList.add("two");

        mockLinkedList.add("three");
        mockLinkedList.add("three");
        mockLinkedList.add("three");//默认一次verify(mockLinkedList).add("one");verify(mockLinkedList,times(1)).add("one");//验证两次、三次verify(mockLinkedList,times(2)).add("two");verify(mockLinkedList,times(3)).add("three");//验证从未添加的元素verify(mockLinkedList,never()).add("never add");//验证atLeast、atMostverify(mockLinkedList,atLeast(1)).add("three");verify(mockLinkedList,atMost(1)).add("one");}

可以使用支持的

times、never、atLeast和atMost

进行调用次数验证。

2.5 stub 空返回值方法

测试demo-5:

@TestvoidstubVoidTest(){LinkedList mockLinkedList =mock(LinkedList.class);doThrow(newRuntimeException()).when(mockLinkedList).clear();//调用clear方法,返回异常
        mockLinkedList.clear();}

执行结果:
在这里插入图片描述

mock

返回值为

void

方法。

2.6 按顺序验证行为

测试demo-6:

@TestvoidverifyInOrderTest(){List singleList =mock(List.class);
        singleList.add("was add first");
        singleList.add("was add second");//单一mock验证顺序InOrder singleInOrder =inOrder(singleList);
        singleInOrder.verify(singleList).add("was add first");
        singleInOrder.verify(singleList).add("was add second");List firstMock =mock(List.class);List secondMock =mock(List.class);

        firstMock.add("one");
        firstMock.add("two");

        secondMock.add("one");
        secondMock.add("two");InOrder order =inOrder(firstMock, secondMock);//多个mock验证添加顺序
        order.verify(firstMock).add("two");
        order.verify(secondMock).add("one");
        order.verify(secondMock).add("two");}

通过

InOrder

进行行为顺序验证,支持多个

mock

对象的顺序验证。

2.7 冗余的mock对象验证

测试demo-7:

@TestvoidredundantInvocationTest(){List mockList =mock(List.class);
        mockList.add("one");
        mockList.add("two");//这个没有验证
        mockList.add("three");verify(mockList).add("two");verify(mockList).add("one");verifyNoMoreInteractions(mockList);}

执行结果:
在这里插入图片描述

verifyNoMoreInteractions

支持验证多余的交互行为(交互了但没有

verify

)。

2.8 迭代器风格的stub

测试demo-8:

@TestvoidstubIteratorTest(){List mockList =mock(List.class);when(mockList.get(1)).thenReturn("foo","test");//按顺序返回System.out.println(mockList.get(1));System.out.println(mockList.get(1));//之后都是最后一个迭代test获胜System.out.println(mockList.get(1));}

执行结果:
在这里插入图片描述

可以返回多个值,每次调用都会向后迭代,超过长度会重复最后一个

stub

的结果。

2.9 支持回调的stub

测试demo-9:

@TestvoidstubWithCallbackTest(){List<String> mockList =mock(List.class);//使用thenAnswer传入回调when(mockList.get(anyInt())).thenAnswer(invocation ->{Object[] arguments = invocation.getArguments();Object mock = invocation.getMock();return"called with arguments: "+Arrays.toString(arguments);});System.out.println(mockList.get(111));}

运行结果:
在这里插入图片描述
支持通过

thenAnswer

传入lambda表达式,自定义回调函数处理返回结果。

2. 10 spy真实对象

测试demo-10:

@TestvoidspyRealObjectTest(){LinkedList<String> linkedList =newLinkedList<>();LinkedList<String> spy =spy(linkedList);

        spy.add("one");
        spy.add("two");System.out.println(spy.get(0));System.out.println(spy.get(1));//进行stubwhen(spy.size()).thenReturn(100);System.out.println(spy.size());verify(spy).add("one");List list =newLinkedList();List spy1 =spy(list);}

运行结果:
在这里插入图片描述

spy

真实对象,将会调用对象的真实方法,同时可以支持

stub

对象行为,但是有局限性,比如下面情况:

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)when(spy1.get(0)).thenReturn("foo");//You have to use doReturn() for stubbingdoReturn("foo").when(spy).get(0);

运行结果:
在这里插入图片描述
因为使用

when,spy.get(0)

将被调用,而此时还没有元素,会抛出异常。而

doReturn

没有调用方法,只是设置了返回值。

2-11 部分真实mock

测试demo-11:

@TestvoidrealPartMockTest(){CalculatorMapper mock =mock(CalculatorMapper.class);//调用selectFirst调用真实方法when(mock.selectFirst(anyInt())).thenCallRealMethod();Assertions.assertEquals(101, mock.selectFirst(1));}
thenCallRealMethod

支持调用真实对象方法。

2-12 重置mock

测试demo-12:

@TestvoidresetMockTest(){List mock =mock(List.class);when(mock.size()).thenReturn(10);
        mock.add(1);//reset所有发生的调用和行为reset(mock);verifyNoMoreInteractions(mock);}

一般我们测试都是针对单独的一个功能,没有必要进行重置。

2-13 @Mock和@InjectMocks

测试demo-13:

@ExtendWith(MockitoExtension.class)publicclassCalculatorManagerTest{//注入mock,会对注入的属性根据测试类中定义的mock类进行注入。@InjectMocksprivateCalculatorService calculatorService;//mock其它类,需要对方法返回值进行mock设置@MockprivateCalculatorMapper calculatorMapper;@BeforeEachvoidsetUp(){}@TestpublicvoidcalculatorManagerTest(){when(calculatorMapper.selectFirst(anyInt())).thenReturn(100);when(calculatorMapper.selectSecond(anyInt())).thenReturn(100);Assertions.assertEquals(200, calculatorService.add(1,1));}}

可以使用注解

@Mock

更简单的

mock

一个对象,如果对象中有注入对象,可以使用

@InjectMocks

进行

mock

对象注入。

2-14 行为驱动开发模式BDD

BDD

一般定义为下:

  • 给定given:场景开头的初始上下文,一个或多个子句.
  • 时间when:触发场景的事件.
  • 然后then:在一个或多个条款中的预期结果。

测试demo-14:

@TestvoidbddMockTest(){List mockList =mock(List.class);//given,列表获取常见given(mockList.get(anyInt())).willReturn(100,200,300);//when,第一次获取
        mockList.get(0);//then,判断获取第二次结果Assertions.assertEquals(mockList.get(0),200);//verify行为的bdd模式then(mockList).should(times(2)).get(0);}

mockito工作组建议使用的编写测试模式。

库中已经封装了对于的

BDD

调用方式。

参考文献

[1] Mockito文档.

标签: java 单元测试 Junit

本文转载自: https://blog.csdn.net/qq_36566262/article/details/124803449
版权归原作者 LamaxiyaFc 所有, 如有侵权,请联系我们删除。

“Java测试-mockito学习”的评论:

还没有评论