美文网首页
2019-03-29 Mockito初探

2019-03-29 Mockito初探

作者: DoubleFooker | 来源:发表于2019-03-29 11:38 被阅读0次

    Mockito初探

    Mockito 可以改变一个类或者对象的行为,能够让我们更加专注地去测试代码逻辑,省去了构造测试数据所花费的努力。

    参考阅读

    概念介绍

    • Mock :可分为两种类型,一种是 Class Mock,另一种是 Partial Mock(Mockito 叫 spy)实例Mock对象。
      • Class Mock
      • Partial Mock (spy)
    • Stub:定义 mock 对象方法(method)的行为 。
      • Stubbing
      • Stubber
      • Answer
    • Verify:验证Stub行为
      • times()
      • never()
      • atLeastOne()
      • atLeast()
      • atMost
      • calls
      • only
      • timeOut
      • after
    • Argument Matcher:参数类型定义,结合Stubbing使用,定义参数类型。同时支持lambda
      • 具体列表查看ArgumentMatchers

    MOCK

    • 示例代码
    import static org.mockito.Mockito.*;
    public class MockitoTest {   
        @Test
        public void test() {
            //Mock:定义Class Mock对象,这里返回的mockedList完全失去了原来的行为
            List mockedList = mock(List.class);
            //Stub:未定义,返回默认值false
            System.out.println(mockedList.add("a"));
           //校验Stub行为合法性。如果是add("b"),则不通过。因为没有定义add("b")的行为
            verify(mockedList).add("a");
        }
    
        @Test
        public void spytest() {
            List list = new LinkedList();
            //定义Partial Mock 实例Mock对象
            List spy = spy(list);
            //定义stub返回false
            when(spy.add("a")).thenReturn(false);
            //返回false 定义了stub
            System.out.println(spy.add("a"));
            //为定义add("b")行为,则调用真实方法
            System.out.println(spy.add("b"));
            //校验
            verify(spy).add("a");
        }
    }
    
    
    • Class Mock 和 Spy的区别

    mock源码

    1:
    @CheckReturnValue
    public static <T> T mock(Class<T> classToMock) {
    //注意withSettings,配置默认返回方式为返回java相关类型的默认值
        return mock(classToMock, withSettings());
    }
    @CheckReturnValue
    public static MockSettings withSettings() {
        return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);
    }
    2:
    @CheckReturnValue
    public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
        return MOCKITO_CORE.mock(classToMock, mockSettings);
    }                               
    

    spy源码

       @CheckReturnValue
        public static <T> T spy(T object) {
            return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
                    .spiedInstance(object)
                     //默认执行对象的真实方法
                    .defaultAnswer(CALLS_REAL_METHODS));
        }   
    

    跟踪源码得到结论,spy和mock方法最大的区别是配置不同的Mock对象MockSetting。使其行为不一样。

    Stub

    • 示例代码
      @Test
        public void stubtest() {
            ArrayList a=new ArrayList();
            List mock=spy(a);
            //List mock=mock(ArrayList.class);
            //这里如果是 spy的类型 会执行真实方法 add("a")
            when(mock.add("a")).thenReturn(false);
            doThrow(new RuntimeException()).when(mock).add("b");
            doReturn(false).when(mock).add("c");
            doAnswer(new Answer() {
                @Override
                public Object answer(InvocationOnMock invocation) throws Throwable {
                    return false;
                }
            }).when(mock).add("d");
            //doCallRealMethod不能定义抽象方法,如是通过mock创建需要配置构造对象
            //OtherAbstract spy = mock(OtherAbstract.class, withSettings().useConstructor().defaultAnswer(CALLS_REAL_METHODS));
            doCallRealMethod().when(mock).add(0,"e");
            //doNothing只能定义void方法
            doNothing().when(mock).clear();
            System.out.println(mock.add("a"));
            System.out.println(mock.add("c"));
            System.out.println(mock.add("d"));
            mock.add(0,"e");
            mock.clear();
            System.out.println(mock.size());
            System.out.println(mock.add("b"));
        }
    

    可通过when|doThrow|doReturn|doAnswer|doCallRealMethod|doNothing定义stub行为,注意spy与class mock使用是的区别。

    Argument Matcher

    • 实例代码
        @Test
        public void argTest() {
            List mock = mock(List.class);
            
            //通过Argument Matcher anytring()定义参数,提供有anyList,anyBoolean等等比较多不一一列举
            when(mock.add(anyString())).thenReturn(false);
            System.out.println(mock.add("a"));
            System.out.println(mock.add("b"));
            List list = new ArrayList();
            List spy = spy(list);
            //支持lambda
            when(spy.add(argThat((String e) -> e.length() < 3))).thenReturn(false);
    
            System.out.println(mock.add("a"));
            System.out.println(mock.add("b"));
            System.out.println(spy.add("b"));
            System.out.println(spy.add("b22"));
    
        }
    

    Argument Matcher 用于定义stubing传入的参数,默认封装了anyString()等常用的测试参数,可以自定义创建需要的测试的参数范围。

    Verify

    • 实例代码
    //verify(mock).someMethod() 相当于 verify(mock, times(1)) 
        @Test
        public void argVerify() {
            List mock = mock(List.class);
            when(mock.add(anyString())).thenReturn(false);
            System.out.println(mock.add("a"));
            System.out.println(mock.add("b"));
            List list = new ArrayList();
            List spy = spy(list);
            when(spy.add(argThat((String e) -> e.length() < 3))).thenReturn(false);
    
            System.out.println(mock.add("a"));
            System.out.println(mock.add("b"));
            System.out.println(spy.add("b"));
            System.out.println(spy.add("b22"));
            // times校验行为调用次数,上面代码块中mock.add("a")执行了两次,如果校验times(1),则不通过
            //times提供了多个方法支持atLeastOnce()等
            verify(mock,times(2)).add("a");
            verify(mock,times(2)).add("b");
            verify(spy).add("b");
            verify(spy).add("b22");
        }
    
    

    用于校验mock对象是否执行了你想要的行为

    相关文章

      网友评论

          本文标题:2019-03-29 Mockito初探

          本文链接:https://www.haomeiwen.com/subject/hvflbqtx.html