Mockito框架的使用
来源:互联网 发布:c语言谭浩强视频百度云 编辑:程序博客网 时间:2024/05/21 11:09
Mockito框架的简单使用
import static org.junit.Assert.assertArrayEquals;import static org.junit.Assert.assertEquals;import static org.mockito.Matchers.anyInt;import static org.mockito.Matchers.anyString;import static org.mockito.Matchers.eq;import static org.mockito.Mockito.inOrder;import static org.mockito.Mockito.mock;import static org.mockito.Mockito.never;import static org.mockito.Mockito.spy;import static org.mockito.Mockito.times;import static org.mockito.Mockito.verify;import static org.mockito.Mockito.verifyNoMoreInteractions;import static org.mockito.Mockito.when;import java.util.Iterator;import java.util.List;import java.util.Map;import org.junit.Test;import org.mockito.ArgumentCaptor;import org.mockito.InOrder;import org.mockito.invocation.InvocationOnMock;import org.mockito.stubbing.Answer;import edu.emory.mathcs.backport.java.util.LinkedList;public class MockitoTest { /** * 通过when(mock.someMethod()).thenReturn(value) 来设定mock对象某个方法调用时的返回值 */ @Test public void simpleTest() { // arrange Iterator i = mock(Iterator.class); when(i.next()).thenReturn("Hello").thenReturn("World"); // act String result = i.next() + " " + i.next(); // 验证i.next()是否被调用了2次,不关心返回值 verify(i, times(2)).next(); // 断言结果是否和预期一样 assertEquals("Hello World", result); } /** * 参数匹配器--Argument matchers test. */ @Test public void argumentMatchersTest() { List<String> mock = mock(List.class); // anyInt()参数匹配器来匹配任何的int 类型的参数 when(mock.get(anyInt())).thenReturn("Hello").thenReturn("World"); // 所以当第一次调用get方法时输入任意参数为100方法返回”Hello”,第二次调用时输入任意参数200返回值”World”。 String result = mock.get(100) + " " + mock.get(200); // verfiy 验证的时候也可将参数指定为anyInt()匹配器,那么它将不关心调用时输入的参数的具体参数值。 verify(mock, times(2)).get(anyInt()); assertEquals("Hello World", result); /* 注意:如果使用了参数匹配器,那么所有的参数需要由匹配器来提供,否则将会报错。 */ } /** * 参数匹配器--Argument matchers test2. */ @SuppressWarnings("unchecked") @Test public void argumentMatchersTest2() { Map<Integer, String> mapMock = mock(Map.class); when(mapMock.put(anyInt(), anyString())).thenReturn("world"); mapMock.put(1, "hello"); // 注:在最后的验证时如果只输入字符串”hello”是会报错的,必须使用Matchers 类内建的eq方法。 // 如果将anyInt()换成1进行验证也需要用eq(1)。 verify(mapMock).put(anyInt(), eq("hello")); } /** * 3.Mock对象的行为验证--Verify test. */ @Test public void verifyTest() { List<String> mock = mock(List.class); List<String> mock1 = mock(List.class); when(mock.get(0)).thenReturn("hello"); mock.get(0); mock.get(1); mock.get(2); mock1.get(0); /* 方法的调用不关心是否模拟了get(2)方法的返回值,只关心mock 对象后,是否执行了mock.get(2),如果没有执行,测试方法将不会通过。 */ verify(mock).get(2); // 验证对象mock是否调用了get(2)方法 verify(mock, never()).get(3); // 方法中可以传入never()方法参数来确认mock.get(3)方法不曾被执行过 /* 确认mock1对象没有进行任何交互===>测试不通过 */ verifyNoMoreInteractions(mock1); // 将其放在 mock1.get(0);之前即可通过。 } /** * 验证方法的调用顺序. */ @Test public void testInvokeOrder() { List<String> firstMock = mock(List.class); List<String> secondMock = mock(List.class); firstMock.add("was called first"); firstMock.add("was called first"); secondMock.add("was called second"); secondMock.add("was called third"); /* 如果mock方法的调用顺序和InOrder中verify的顺序不同,那么测试将执行失败。 */ InOrder inOrder = inOrder(secondMock, firstMock); inOrder.verify(firstMock, times(2)).add("was called first"); inOrder.verify(secondMock).add("was called second"); // 因为在secondMock.add("was called third")之后已经没有多余的方法调用了。 inOrder.verify(secondMock).add("was called third"); inOrder.verifyNoMoreInteractions();// 表示此方法调用后再没有多余的交互 } /** * 自定义Answer接口(方法预期回调接口)的应用 */ @Test public void customAnswerTest() { List<String> mock = mock(List.class); when(mock.get(4)).thenAnswer(new Answer() { public String answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); Integer num = (Integer) args[0]; if (num > 3) { return "yes"; } throw new RuntimeException(); } }); System.out.println(mock.get(4)); } /** * 利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证 */ @Test public void argumentCaptorTest() { List mock = mock(List.class); List mock2 = mock(List.class); mock.add("John"); mock2.add("Brian"); mock2.add("Jim"); /* * 首先构建ArgumentCaptor需要传入捕获参数的对象,例子中是String。接着要在 verify 方法的参数中调用argument.capture()方法来捕获输入的参数, <br> 之后 * argument变量中就保存了参数值,可以用argument.getValue()获取。 */ ArgumentCaptor argument = ArgumentCaptor.forClass(String.class); verify(mock).add(argument.capture()); assertEquals("John", argument.getValue()); verify(mock2, times(2)).add(argument.capture()); assertEquals("Jim", argument.getValue()); /* argument.getAllValues(),它将返回参数值的List。 */ assertArrayEquals(new Object[] { "John", "Brian", "Jim" }, argument.getAllValues().toArray()); } /** * Spy-对象的监视<br> * Mock 对象只能调用stubbed 方法,调用不了它真实的方法。但Mockito 可以监视一个真实的对象,这时对它进行方法调用时它将调用真实的方法,<br> * 同时也可以stubbing 这个对象的方法让它返回我们的期望值。另外不论是否是真实的方法调用都可以进行verify验证。<br> * 和创建mock对象一样,对于final类、匿名类和Java的基本类型是无法进行spy的。 */ @Test public void spyTest2() { List list = new LinkedList(); List spy = spy(list); // optionally, you can stub out some methods: when(spy.size()).thenReturn(100); // using the spy calls real methods spy.add("one"); spy.add("two"); // prints "one" - the first element of a list System.out.println(spy.get(0)); // size() method was stubbed - 100 is printed System.out.println(spy.size()); // optionally, you can verify verify(spy).add("one"); verify(spy).add("two"); }}
Mockito框架注解的使用
Mockito对Annotation的支持
Mockito 支持对变量进行注解,例如将mock 对象设为测试类的属性,然后通过注解的方式@Mock 来定义它,这样有利于减少重复代码,增强可读性,易于排查错误等。
除了支持@Mock,Mockito支持的注解还有@Spy(监视真实的对象),@Captor(参数捕获器),@InjectMocks(mock对象自动注入)。
Annotation的初始化
Annotation的初始化只有Annotation还不够,要让它们工作起来还需要进行初始化工作。初始化的方
法为:MockitoAnnotations.initMocks(testClass),参数testClass是你所写的测试类。一般情况下在Junit4的@Before 定义的方法中执行初始化工作,如下:
@Beforepublic void initMocks() {MockitoAnnotations.initMocks(this);}
除了上述的初始化的方法外,还可以使用Mockito 提供的Junit Runner:
MockitoJUnitRunner这样就省略了上面的步骤。
@RunWith(MockitoJUnit44Runner.class)public class ExampleTest {...}
@Mock 注解
使用@Mock注解来定义mock对象有如下的优点:
- 方便mock对象的创建
- 减少mock对象创建的重复代码
- 提高测试代码可读性
- 变量名字作为mock对象的标示,所以易于排错
@Mock注解也支持自定义name 和answer属性。下面是官方给出的@Mock使用的例子:
public class ArticleManagerTest extends SampleBaseTestCase { @Mock private ArticleCalculator calculator; @Mock(name = "dbMock") private ArticleDatabase database; @Mock(answer = RETURNS_MOCKS) private UserProvider userProvider; private ArticleManager manager; @Before public void setup() { manager = new ArticleManager(userProvider, database, calculator); }}public class SampleBaseTestCase { @Before public void initMocks() { MockitoAnnotations.initMocks(this); }}
@Spy 注解
public class Test { @Spy Foo spyOnFoo = new Foo(); @Before public void init() { MockitoAnnotations.initMocks(this); }}
@Captor 注解
public class Test { @Captor ArgumentCaptor<AsyncCallback<Foo>> captor; @Before public void init() { MockitoAnnotations.initMocks(this); } @Test public void shouldDoSomethingUseful() { // ... verify(mock.doStuff(captor.capture())); assertEquals("foo", captor.getValue()); }}
@InjectMocks 注解
通过这个注解,可实现自动注入mock 对象。当前版本只支持setter 的方式进行注入,Mockito 首先尝试类型注入,如果有多个类型相同的mock 对象,那么它会根据名称进行注入。当注入失败的时候Mockito不会抛出任何异常,所以你可能需要手动去验证它的安全性。
@RunWith(MockitoJUnit44Runner.class)public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Spy private UserProvider userProvider = new ConsumerUserProvider(); @InjectMocks private ArticleManager manager = new ArticleManager(); @Test public void shouldDoSomething() { manager.initiateArticle(); verify(database).addListener(any(ArticleListener.class)); }}
上例中, ArticleDatabase 是ArticleManager 的一个属性, 由于
ArticleManager 是注解@InjectMocks 标注的,所以会根据类型自动调用它的
setter方法为它设置ArticleDatabase
【转自TZQ_DO_Dreamer】
(http://blog.csdn.net/u010834071/article/details/47665791)
- Mockito框架的使用
- Android单元测试(二):Mockito框架的使用
- Mockito java单元测试框架使用
- Mockito的使用笔记
- Mockito的使用笔记
- Mockito的使用
- Mockito的使用一
- Mockito的使用 二
- Mockito的使用
- 强大的Mockito测试框架
- 强大的Mockito测试框架
- 强大的Mockito测试框架
- 强大的Mockito测试框架
- 测试框架Mockito的学习
- Mockito框架
- Mock以及Mockito的使用
- Mock以及Mockito的使用
- Mock以及Mockito的使用
- 反射获取静态属性
- struts基础
- "神经网络入门" 笔记
- Ubuntu16.04 下设置桌面快捷方式
- S5PV210的定时器
- Mockito框架的使用
- Semantic UI实现一个landing page
- 网上的资源
- Java中的锁-Lock
- Unity功能界面详解
- 趣图:如今的程序员招聘
- 2-16进制数之间的转化
- 小迪教程第十一天——绕过本地端js验证
- 基于Maven的Spring+SpringMVC+Hibernate 邮箱验证码