JUnit + Mockito 单元测试

2023-02-19,,

JUnit + Mockito 单元测试(二)

2015年01月05日 17:26:02
sp42a
阅读数:60755

																														</div>
<div class="operating">
</div>
</div>
</div>
</div>
<article>
<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
<div class="article-copyright">
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangxin09/article/details/42422643 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-e4c7a3727d.css">
<div class="htmledit_views">
<p>JUnit 是单元测试框架。Mockito 与 JUnit 不同,并不是单元测试框架(这方面 JUnit 已经足够好了),它是用于生成模拟对象或者直接点说,就是”假对象“的工具。两者定位不同,所以一般通常的做法就是联合 JUnit + Mockito 来进行测试。</p><h2><a name="t0"></a>入门</h2><p>首先是配置 Mock 对象,看看例子怎么写的。</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">List mock = mock( List.class );</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when( mock.get(<span class="hljs-number">0</span>) ).thenReturn( <span class="hljs-number">1</span> );</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">assertEquals( <span class="hljs-string">"预期返回1"</span>, <span class="hljs-number">1</span>, mock.get( <span class="hljs-number">0</span> ) );<span class="hljs-comment">// mock.get(0) 返回 1</span></div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>其中 mock 是模拟 List 的对象,拥有 List 的所有方法和属性。when(xxxx).thenReturn(yyyy); 是指定当执行了这个方法的时候,返回 thenReturn 的值,相当于是对模拟对象的配置过程,为某些条件给定一个预期的返回值。相信通过这个简单的例子你可以明白所谓 Mock 便是这么一回事。</p><p>我们看到 List 为 Java.util.List 是接口,并不是实现类,但这不妨碍我们使用它作为我们的“打桩”对象,——当然你也可以使用实现类,传入 mock(obj) 方法中。这里提到的是"打桩(Stub,也有人称其为“存根”)"的概念,是一个形象的说法,就是把所需的测试数据塞进对象中,适用于基于状态的(state-based)测试,关注的是输入和输出。Mockito 中 when(…).thenReturn(…)&nbsp; 这样的语法来定义对象方法和参数(输入),然后在 thenReturn 中指定结果(输出)。此过程称为 Stub 打桩。一旦这个方法被 stub 了,就会一直返回这个 stub 的值。</p><p>打桩需要<a href="http://qiuguo0205.iteye.com/blog/1443344" rel="nofollow" target="_blank">注意以下几点</a>:</p><ul><li>对于 static 和 final 方法, Mockito 无法对其 when(…).thenReturn(…) 操作。</li><li>当我们连续两次为同一个方法使用 stub 的时候,他只会只用最新的一次。</li></ul><p>mock 对象会覆盖整个被 mock 的对象,因此没有 stub 的方法只能返回默认值。又因为,我们 mock 一个接口的时候,很多成员方法只是一个签名,并没有实现,这就要我们手动写出这些实现方法啦。典型地,我们模拟一个 request 请求对象,你被测试的代码中使用了 HttpSerevletRequest 什么方法,就要写出相应的实现方法!</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">HttpServletRequest request = mock(HttpServletRequest.class);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(request.getParameter(<span class="hljs-string">"foo"</span>)).thenReturn(<span class="hljs-string">"boo"</span>);</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>这里“打桩”之后,我们执行 request.getParamter("foo") 就会返回 boo,如果不这样设定,Mockito 就会返回默认的 null,也不会报错说这个方法找不到。mock 实例默认的会给所有的方法添加基本实现:返回 null 或空集合,或者 0 等基本类型的值。这取决于方法返回类型,如 int 会返回 0,布尔值返回 false。对于其他 type 会返回 null。</p><p>打桩支持迭代风格的返回值设定,例如,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 第一种方式 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(i.next()).thenReturn(<span class="hljs-string">"Hello"</span>).thenReturn(<span class="hljs-string">"World"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 第二种方式</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(i.next()).thenReturn(<span class="hljs-string">"Hello"</span>, <span class="hljs-string">"World"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 第三种方式,都是等价的</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(i.next()).thenReturn(<span class="hljs-string">"Hello"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(i.next()).thenReturn(<span class="hljs-string">"World"</span>);</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>第一次调用 i.next() 将返回 ”Hello”,第二次的调用会返回 ”World”。</p><p>上述我们一直在讨论被测试的方法都有返回值的,那么没有返回值的 void 方法呢?也是测试吗?答案是肯定的。——只不过 Mockito 要求你的写法上有不同,因为都没返回值了,调用 thenReturn(xxx) 肯定不行,取而代之的写法是,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">doNothing().when(obj).notify();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 或直接</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(obj).notify();</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>Mockito 还能对被测试的方法强行抛出异常,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln" style="width:1163px"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(i.next()).thenThrow(<span class="hljs-keyword">new</span> RuntimeException());</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">doThrow(<span class="hljs-keyword">new</span> RuntimeException()).when(i).remove(); <span class="hljs-comment">// void 方法的</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 迭代风格 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">doNothing().doThrow(<span class="hljs-keyword">new</span> RuntimeException()).when(i).remove(); <span class="hljs-comment">// 第一次调用 remove 方法什么都不做,第二次调用抛出 RuntimeException 异常。</span></div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>如需指定异常类型,参见<a href="http://blog.sina.com.cn/s/blog_6176c38201014ll2.html" rel="nofollow" target="_blank">这里</a>。 </p><h2><a name="t1"></a><strong>模拟传入的参数</strong> argument matchers</h2><p>拿上面的例子说,其中一个问题,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs">when(request.getParameter(<span class="hljs-string">"foo"</span>)).thenReturn(<span class="hljs-string">"boo"</span>);</code><div class="hljs-button" data-title="复制"></div></pre><p>这里 getParameter("foo") 这里我们是写死参数 foo 的,但是如果我不关心输入的具体内容,可以吗?可以的,最好能像正则表达式那样,/w+ 表示任意字符串是不是很方便,不用考虑具体什么参数,只要是 字符串 型的参数,就可以打桩。如此方便的想法 Mockito 也考虑到了,提供 argument matchers 机制,例如 anyString() 匹配任何 String 参数,anyInt() 匹配任何 int 参数,anySet() 匹配任何 Set,any() 则意味着参数为任意值。例子如下,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(mockedList.get(anyInt())).thenReturn(<span class="hljs-string">"element"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">System.out.println(mockedList.get(<span class="hljs-number">999</span>));<span class="hljs-comment">// 此时打印是 element </span></div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>再进一步,自定义类型也可以,如 any(User.class),另,参见<a href="http://hotdog.iteye.com/blog/911584" rel="nofollow" target="_blank">《学习 Mockito - 自定义参数匹配器》</a> 和 <a href="http://blog.sina.com.cn/s/blog_6176c38201014jrk.html" rel="nofollow" target="_blank">这里</a> 和 <a href="http://blog.csdn.net/onlyqi/article/details/6544989" rel="nofollow" target="_blank">这里</a>。</p><h2><a name="t2"></a>获取返回的结果</h2><p>一个问题,thenReturn 是返回结果是我们写死的。如果要让被测试的方法不写死,返回实际结果并让我们可以获取到的——怎么做呢?有时我们需要自定义方法执行的返回结果,Answer 接口就是满足这样的需求而存在的。</p><p>例如模拟常见的 request.getAttribute(key),由于这本来是个接口,所以连内部实现都要自己写了。此次通过 Answer 接口获取参数内容。</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">final</span> Map&lt;String, Object&gt; hash = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">Answer&lt;String&gt; aswser = <span class="hljs-keyword">new</span> Answer&lt;String&gt;() { &nbsp;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&nbsp;&nbsp;&nbsp; <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">answer</span><span class="hljs-params">(InvocationOnMock invocation)</span> </span>{ &nbsp;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] args = invocation.getArguments(); &nbsp;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-keyword">return</span> hash.get(args[<span class="hljs-number">0</span>].toString()).toString(); &nbsp;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">&nbsp;&nbsp;&nbsp; } </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">};</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(request.getAttribute(<span class="hljs-string">"isRawOutput"</span>)).thenReturn(<span class="hljs-keyword">true</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(request.getAttribute(<span class="hljs-string">"errMsg"</span>)).thenAnswer(aswser); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(request.getAttribute(<span class="hljs-string">"msg"</span>)).thenAnswer(aswser);</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>利用 InvocationOnMock 提供的方法可以获取 mock 方法的调用信息。下面是它提供的方法:</p><ul><li>getArguments() 调用后会以 Object 数组的方式返回 mock 方法调用的参数。</li><li>getMethod() 返回 java.lang.reflect.Method 对象</li><li>getMock() 返回 mock 对象</li><li>callRealMethod() 真实方法调用,如果 mock 的是接口它将会抛出异常</li></ul><p>void 方法可以获取参数,只是写法上有区别,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">doAnswer(<span class="hljs-keyword">new</span> Answer&lt;Object&gt;() {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">answer</span><span class="hljs-params">(InvocationOnMock invocation)</span> </span>{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> Object[] args = invocation.getArguments();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// Object mock = invocation.getMock(); </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> System.out.println(args[<span class="hljs-number">1</span>]);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> hash.put(args[<span class="hljs-number">0</span>].toString(), args[<span class="hljs-number">1</span>]);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">return</span> <span class="hljs-string">"called with arguments: "</span> + args;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}).when(request).setAttribute(anyString(), anyString());</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>其实就是一个回调,——如果不是接口,是实现类的话,估计不用自己写实现。</p><h2><a name="t3"></a>验证 Verify</h2><p>前面提到的 when(……).thenReturn(……) 属于状态测试,某些时候,测试不关心返回结果,而是侧重方法有否被正确的参数调用过,这时候就应该使用 验证方法了。从概念上讲,就是和状态测试所不同的“行为测试”了。</p><p>一旦使用 mock() 对模拟对象打桩,意味着 Mockito 会记录着这个模拟对象调用了什么方法,还有调用了多少次。最后由用户决定是否需要进行验证,即 verify() 方法。</p><p>verify() 说明其作用的例子,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">mockedList.add(<span class="hljs-string">"one"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">mockedList.add(<span class="hljs-string">"two"</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mockedList).add(<span class="hljs-string">"one"</span>); <span class="hljs-comment">// 如果times不传入,则默认是1</span></div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>verify 内部跟踪了所有的方法调用和参数的调用情况,然后会返回一个结果,说明是否通过。参见另外一个详细的例子。 </p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">Map mock = Mockito.mock( Map.class );</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when( mock.get( <span class="hljs-string">"city"</span> ) ).thenReturn( <span class="hljs-string">"广州"</span> );</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 关注参数有否传入</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mock).get( Matchers.eq( <span class="hljs-string">"city"</span> ) );</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 关注调用的次数</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mock, times( <span class="hljs-number">2</span> )); </div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>也就是说,这是对历史记录作一种回溯校验的处理。</p><p>这里补充一个学究的问题,所谓 Mock 与 Stub 打桩,其实它们之间不能互为其表。但 Mockito 语境中则 <a href="http://stamen.iteye.com/blog/1470066" rel="nofollow" target="_blank">Stub 和 Mock 对象同时使用的</a>。因为它既可以设置方法调用返回值,又可以验证方法的调用。有关 stub 和 mock 的详细论述请见 Martin Fowler 大叔的文章<a href="http://martinfowler.com/articles/mocksArentStubs.html" rel="nofollow" target="_blank">《Mocks Aren't Stub》</a>。</p><p>Mockito 除了提供 times(N) 方法供我们调用外,还提供了很多可选的方法:</p><ul><li>never() 没有被调用,相当于 times(0)</li><li>atLeast(N) 至少被调用 N 次</li><li>atLeastOnce() 相当于 atLeast(1)</li><li>atMost(N) 最多被调用 N 次</li></ul><p>verify 也可以像 when 那样使用模拟参数,若方法中的某一个参数使用了matcher,则所有的参数都必须使用 matcher。</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// correct </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mock).someMethod(anyInt(), anyString(), eq(<span class="hljs-string">"third argument"</span>)); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// will throw exception </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mock).someMethod(anyInt(), anyString(), <span class="hljs-string">"third argument"</span>); </div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>在最后的验证时如果只输入字符串”hello”是会报错的,必须使用 Matchers 类内建的 eq 方法。</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">Map mapMock = mock(Map.class); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(mapMock.put(anyInt(), anyString())).thenReturn(<span class="hljs-string">"world"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">mapMock.put(<span class="hljs-number">1</span>, <span class="hljs-string">"hello"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(mapMock).put(anyInt(), eq(<span class="hljs-string">"hello"</span>));</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>其他高级用法,详见<a href="http://hotdog.iteye.com/blog/908827" rel="nofollow" target="_blank">《学习 Mockito - Mock对象的行为验证》</a>,主要特性如下,</p><ul><li>参数验证,详见<a href="http://hotdog.iteye.com/blog/916364" rel="nofollow" target="_blank">《利用 ArgumentCaptor(参数捕获器)捕获方法参数进行验证》</a></li><li>超时验证,通过 timeout,并制定毫秒数验证超时。注意,如果被调用多次,times 还是需要的。</li><li>方法调用顺序 通过 InOrder 对象,验证方法的执行顺序,如上例子中,如果 mock 的 get(0) 和 get(1) 方法反过来则测试不通过。这里 mock2 其实没有被调用过。所以不需要些。</li><li>verifyNoMoreInteractions 查询是否存在被调用,但未被验证的方法,如果存在则抛出异常。这里因为验证了get(anyInt()),相当于所有的 get 方法被验证,所以通过。</li><li>verifyZeroInteractions 查询对象是否未产生交互,如果传入 的 mock 对象的方法被调用过,则抛出异常。这里 mock2 的方法没有被调用过,所有通过。</li></ul><p>参见<a href="http://blog.sina.com.cn/s/blog_6176c38201014lzc.html" rel="nofollow" target="_blank">《用mockito的verify来验证mock的方法是否被调用》</a>:</p><blockquote><p><span style="color:#666666;">看mockito的api时,一直都不清楚veriry()这个方法的作用,因为如果我mock了某个方法,肯定是为了调用的啊。直到今天在回归接口测试用例的时候,发现有两个用例,用例2比用例1多了一个 mock 的步骤,不过最后的结果输出是一样的。由于代码做了修改,我重新 mock 后,其实用例2中对于的步骤是不会执行的,可测试还是通过了。仔细查看后,发现mock的方法没有被调用,所以用例2和用例1就变成一样的了。于是,就产生了这么个需求:单单通过结果来判断正确与否还是不够的,我还要判断是否按我指定的路径执行的用例。到这里,终于领略到了mockito的verify的强大威力,以下是示例代码:</span></p><p><span style="color:#666666;">若调用成功,则程序正常运行,反之则会报告: Wanted but not invoked:verify(mockedList).add("one"); 错误。</span></p></blockquote><p>感觉 verify 会用的比较少。</p><h2><a name="t4"></a>Spy</h2><p><a href="http://qiuguo0205.iteye.com/blog/1456528" rel="nofollow" target="_blank">spy 的意思</a>是你可以修改某个真实对象的某些方法的行为特征,而不改变他的基本行为特征,这种策略的使用跟 AOP 有点类似。下面举官方的例子来说明:</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">List list = <span class="hljs-keyword">new</span> LinkedList(); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">List spy = spy(list); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">//optionally, you can stub out some methods: </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">when(spy.size()).thenReturn(<span class="hljs-number">100</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">//using the spy calls &lt;b&gt;real&lt;/b&gt; methods </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">spy.add(<span class="hljs-string">"one"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">spy.add(<span class="hljs-string">"two"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">//prints "one" - the first element of a list </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">System.out.println(spy.get(<span class="hljs-number">0</span>)); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">//size() method was stubbed - 100 is printed </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">System.out.println(spy.size()); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">//optionally, you can verify </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(spy).add(<span class="hljs-string">"one"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">verify(spy).add(<span class="hljs-string">"two"</span>);</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>可以看到 spy 保留了 list 的大部分功能,只是将它的 size() 方法改写了。不过 spy 在使用的时候有很多地方需要注意,一不小心就会导致问题,所以不到万不得已还是不要用 spy。</p><h2><a name="t5"></a>总结例子</h2><p>出处在<a href="http://sgq0085.iteye.com/blog/2031319" rel="nofollow" target="_blank">这里</a>。</p><p></p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln" style="width:875px"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Test</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">()</span> </span>{ </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> User user = <span class="hljs-keyword">new</span> User(); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> user.setLoginName(<span class="hljs-string">"admin"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 第一次调用findUserByLoginName返回user 第二次调用返回null </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> when(mockUserDao.findUserByLoginName(anyString())).thenReturn(user).thenReturn(<span class="hljs-keyword">null</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">try</span> { </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 测试如果重名会抛出异常 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> userService.save(user); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 如果没有抛出异常测试不通过 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> failBecauseExceptionWasNotThrown(RuntimeException.class); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } <span class="hljs-keyword">catch</span> (ServiceException se) { </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> verify(mockUserDao).findUserByLoginName(<span class="hljs-string">"admin"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// userService.save(user); </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> user.setPassword(<span class="hljs-string">"123456"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> String userId = userService.save(user); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 断言返回结果 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> assertThat(userId).isNotEmpty().hasSize(<span class="hljs-number">32</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> verify(mockUserDao, times(<span class="hljs-number">2</span>)).findUserByLoginName(anyString()); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> verify(mockUserDao).save(any(User.class)); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Test</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="27"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save2</span><span class="hljs-params">()</span> </span>{ </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="28"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> User user = <span class="hljs-keyword">new</span> User(); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="29"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> user.setLoginName(<span class="hljs-string">"admin"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="30"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> user.setPassword(<span class="hljs-string">"123456"</span>); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="31"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> userService.save(user); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="32"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="33"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 通过ArgumentCaptor(参数捕获器) 对传入参数进行验证 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="34"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> ArgumentCaptor&lt;User&gt; argument = ArgumentCaptor.forClass(User.class); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> verify(mockUserDao).save(argument.capture()); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="36"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> assertThat(<span class="hljs-string">"admin"</span>).isEqualTo(argument.getValue().getLoginName()); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="37"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="38"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// stub 调用save方法时抛出异常 </span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="39"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> doThrow(<span class="hljs-keyword">new</span> ServiceException(<span class="hljs-string">"测试抛出异常"</span>)).when(mockUserDao).save(any(User.class)); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="40"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">try</span> { </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> userService.save(user); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> failBecauseExceptionWasNotThrown(RuntimeException.class); </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="43"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } <span class="hljs-keyword">catch</span> (ServiceException se) { </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="44"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="45"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> } </div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p></p><h2><a name="t6"></a>其他高级话题</h2><p>如果没有 JUnit,可以使用 Mockito 的 @Before 的注解,进行一些前期的初始化工作,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArticleManagerTest</span> </span>{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Mock</span> <span class="hljs-keyword">private</span> ArticleCalculator calculator;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Mock</span> <span class="hljs-keyword">private</span> ArticleDatabase database;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Mock</span> <span class="hljs-keyword">private</span> UserProvider userProvider;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Before</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> MockitoAnnotations.initMocks(testClass);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">} </div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>如果有 JUnit,则无需 @Before,但要修改 JUnit 默认容器,</p><pre onclick="hljs.copyCode(event)"><code class="language-java hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-meta">@RunWith</span>(MockitoJUnitRunner.class)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExampleTest</span> </span>{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Mock</span> <span class="hljs-keyword">private</span> List list;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-meta">@Test</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">shouldDoSomething</span><span class="hljs-params">()</span> </span>{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> list.add(<span class="hljs-number">100</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button" data-title="复制"></div></pre><p>在 JUnit 中有很多个 Runner ,他们负责调用你的测试代码,每一个 Runner 都有各自的特殊功能,你要根据需要选择不同的 Runner 来运行你的测试代码。<br></p><p>----------------------------------------------------<br></p><p>貌似 Mockito 的注解都比较强大,有待以后再看看:</p><p><a href="http://hotdog.iteye.com/blog/937862" rel="nofollow" target="_blank">《学习Mockito - Mockito对Annotation的支持》</a>, <a href="http://jilen.iteye.com/blog/1427368" rel="nofollow" target="_blank">http://jilen.iteye.com/blog/1427368</a></p><p>参见资源:</p><ul><li><a href="http://hotdog.iteye.com/?page=2" rel="nofollow" target="_blank">Mockito 专栏博客</a><br></li><li><a href="http://blog.csdn.net/OnlyQi/article/details/6546589" rel="nofollow" target="_blank">Mockito(二)--实例篇 <br></a></li></ul> </div>
</div> <script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>

posted @
2018-10-23 11:43 
jobs-lgy 
阅读(...) 
评论(...) 
编辑 
收藏

markdown_highlight();

var allowComments = true, cb_blogId = 317248, cb_blogApp = 'jobs-lgy', cb_blogUserGuid = 'f2023aea-afab-e611-845c-ac853d9f53ac';
var cb_entryId = 9835775, cb_entryCreatedDate = '2018-10-23 11:43', cb_postType = 1;
loadViewCount(cb_entryId);
loadSideColumnAd();

var commentManager = new blogCommentManager();
commentManager.renderComments(0);

刷新评论刷新页面返回顶部

var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];

googletag.cmd.push(function () {
googletag.defineSlot("/1090369/C1", [300, 250], "div-gpt-ad-1546353474406-0").addService(googletag.pubads());
googletag.defineSlot("/1090369/C2", [468, 60], "div-gpt-ad-1539008685004-0").addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});

fixPostBody();
deliverBigBanner();
setTimeout(function() { incrementViewCount(cb_entryId); }, 50); deliverAdT2();
deliverAdC1();
deliverAdC2();
loadNewsAndKb();
loadBlogSignature();
LoadPostCategoriesTags(cb_blogId, cb_entryId); LoadPostInfoBlock(cb_blogId, cb_entryId, cb_blogApp, cb_blogUserGuid);
GetPrevNextPost(cb_entryId, cb_blogId, cb_entryCreatedDate, cb_postType);
loadOptUnderPost();
GetHistoryToday(cb_blogId, cb_blogApp, cb_entryCreatedDate);

JUnit + Mockito 单元测试的相关教程结束。

《JUnit + Mockito 单元测试.doc》

下载本文的Word格式文档,以方便收藏与打印。