美文网首页
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