用 Mockito 模拟 Void 方法

单元测试 Mar 02, 2020 阅读

原文:https://www.baeldung.com/mockito-void-methods
翻译:杨金龙

1. 概述

这个教程,我们主要关注如何使用Mockito模拟void方法

使用一个MyList类,来作为被测试的类

public class MyList extends AbstractList<String> {
  
    @Override
    public void add(int index, String element) {
        // no-op
    }
}

2. 简单的模拟和验证

Void 方法可以与 Mockito 的 doNothing()、 doThrow()和 doAnswer()方法一起使用,使模拟和验证更加直观:

@Test
public void whenAddCalledVerified() {
    MyList myList = mock(MyList.class);
    doNothing().when(myList).add(isA(Integer.class), isA(String.class));
    myList.add(0, "");
  
    verify(myList, times(1)).add(0, "");
}

但是,doNothing()是 Mockito 的 void 方法的默认行为。

这个版本的whenAddCalledVerified()完成了与上面一个相同的事情:

@Test
public void whenAddCalledVerified() {
    MyList myList = mock(MyList.class);
    myList(0, "");
  
    verify(myList, times(1)).add(0, "");
}

Dothrow()生成一个异常:

@Test(expected = Exception.class)
public void givenNull_AddThrows() {
    MyList myList = mock(MyList.class);
    doThrow().when(myList).add(isA(Integer.class), isNull());
  
    myList.add(0, null);
}

我们接下来讨论doAnswer()

3. 捕获参数

使用 doNothing()覆盖默认行为的一个原因是捕获参数。

在上面的示例中,我们使用 verify()检查传递给 add()的参数。

我们可能需要捕获这些参数,可以像上面一样使用 doNothing() ,再加一个 ArgumentCaptor:

@Test
public void whenAddCalledValueCaptured() {
    MyList myList = mock(MyList.class);
    ArgumentCaptor<String> valueCapture = ArgumentCaptor.forClass(String.class);
    doNothing().when(myList).add(any(Integer.class), valueCapture.capture());
    myList.add(0, "captured");
  
    assertEquals("captured", valueCapture.getValue());
}

4. Answering a Call to Void

方法可能执行比仅仅增加或设置值更复杂的行为。 对于这些情况,我们可以使用 Mockito 的回答来添加我们需要的行为:

@Test
public void whenAddCalledAnswered() {
    MyList myList = mock(MyList.class);
    doAnswer(invocation -> {
        Object arg0 = invocation.getArgument(0);
        Object arg1 = invocation.getArgument(1);
         
        assertEquals(3, arg0);
        assertEquals("answer me", arg1);
        return null;
    }).when(myList).add(any(Integer.class), any(String.class));
    myList.add(3, "answer me");
}

我们使用带有 Answer 的 lambda 来定义 add()的定制行为。

5. 部分模拟

部分模拟也是一个选择, Mockito 的 doCallRealMethod()可用于 void 方法:

@Test
public void whenAddCalledRealMethodCalled() {
    MyList myList = mock(MyList.class);
    doCallRealMethod().when(myList).add(any(Integer.class), any(String.class));
    myList.add(1, "real");
  
    verify(myList, times(1)).add(1, "real");
}

这样,我们可以调用实际的方法并同时验证它。

6. 总结

这个教程,我们介绍了在使用 Mockito 进行测试时处理 void 方法的四种不同方法。

这些例子可以在这个 GitHub 项目中找到。