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);

最新文章

  1. Maven 配置使用小技巧
  2. VMware与virtualbox安装centos7连接网络不可达问题解决笔记(连接网络)
  3. CentOS yum的详细使用方法
  4. 导入maven工程遇见的问题【问题】
  5. js中的fadeIn()
  6. 修改phpmyadmin文件的最大上传大小
  7. mp3 音频 音乐 tag ID3 ID3V1 ID3V2 标签 读取信息 获得图片 jpeg bmp 图片转换等
  8. OpenJudge 666:放苹果
  9. mahout协同过滤算法
  10. 【原创】linux命令bc使用详解
  11. c# 大数据量比较时-方案
  12. C++学习笔记36 (模板的细节明确template specialization)和显式实例(template instantiation)
  13. SpringBoot文档翻译系列——29.SQL数据源
  14. Confluence 6 使用 Apache 和 mod_proxy 添加 SSL和其他
  15. 自动化监控白皮书——WAS监控
  16. 为什么说 HashMap 是非线程安全的?
  17. kafka产生的数据通过Flume存到HDFS中
  18. Servlet基本_サーブレットのライフサイクル、スレッドセーフ
  19. sqlserver -- 查看当前数据库的数据表(备忘)
  20. Oracle数据库日期范围查询的两种实现方式

热门文章

  1. C语言程序设计(三)——顺序程序设计
  2. C++ 宏定义创建(销毁)单例
  3. Hello 2020D(多重集)
  4. python之nosetest
  5. yii2时区语言设置
  6. Hadoop 启动/停止集群和节点的命令
  7. EFCore.BulkExtensions Demo
  8. 关于C++指针、引用和const关键字的各种关系
  9. C++模板详解(三):参数化声明详解
  10. 红帽RHCE培训-课程1笔记目录