﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-少年阿宾-随笔分类-easyMock</title><link>http://www.blogjava.net/stevenjohn/category/52961.html</link><description>那些青春的岁月</description><language>zh-cn</language><lastBuildDate>Tue, 23 Apr 2013 08:22:04 GMT</lastBuildDate><pubDate>Tue, 23 Apr 2013 08:22:04 GMT</pubDate><ttl>60</ttl><item><title>EasyMock 初步学习用例（一）</title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/23/398273.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 23 Apr 2013 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/23/398273.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398273.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/23/398273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398273.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398273.html</trackback:ping><description><![CDATA[<div class="blog_content">//EasyMockServlet.java <br />package com.abin.lee.easymock.servlets; <br /><br />import javax.servlet.RequestDispatcher; <br />import javax.servlet.ServletContext; <br />import javax.servlet.ServletException; <br />import javax.servlet.http.HttpServlet; <br />import javax.servlet.http.HttpServletRequest; <br />import javax.servlet.http.HttpServletResponse; <br />import java.io.IOException; <br /><br />/** <br />* Created with IntelliJ IDEA. <br />* User: abin <br />* Date: 13-4-22 <br />* Time: 下午3:12 <br />* To change this template use File | Settings | File Templates. <br />*/ <br />public class EasyMockServlet extends HttpServlet { <br />&nbsp;&nbsp;&nbsp; public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("doPost come in"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String userName=request.getParameter("userName"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String passWord=request.getParameter("passWord"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("userName="+userName+",passWord="+passWord); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if("abin".equals(userName)&amp;&amp;"varyall".equals(passWord)){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("come in"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServletContext context=this.getServletContext(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RequestDispatcher dispatcher=context.getNamedDispatcher("dispatcher"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatcher.forward(request,response); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new RuntimeException("Login failed."); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; } <br /><br />} <br /><br /><br /><br /><br /><br />//EasyMockServletFailedTest.java <br />package com.abin.lee.easymock.servlets; <br /><br />import org.easymock.EasyMock; <br />import org.easymock.IMocksControl; <br />import org.junit.Test; <br /><br />import javax.servlet.http.HttpServletRequest; <br /><br />import static junit.framework.TestCase.assertEquals; <br />import static org.junit.Assert.fail; <br /><br />/** <br />* Created with IntelliJ IDEA. <br />* User: abin <br />* Date: 13-4-22 <br />* Time: 下午5:08 <br />* To change this template use File | Settings | File Templates. <br />*/ <br />public class EasyMockServletFailedTest { <br />&nbsp;&nbsp;&nbsp; @Test <br />&nbsp;&nbsp;&nbsp; public void testEasyMockServletFailed(){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request=EasyMock.createMock(HttpServletRequest.class); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expect(request.getParameter("userName")).andReturn("abin"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").times(1); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.replay(request); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMockServlet easyMockServlet=new EasyMockServlet(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; easyMockServlet.doPost(request,null); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fail("Not caught exception!"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals("Login failed.", e.getMessage()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.verify(request); <br />&nbsp;&nbsp;&nbsp; } <br />} <br /><br /><br /><br /><br /><br /><br />//EasyMockServletSuccessTest <br />package com.abin.lee.easymock.servlets; <br /><br />import org.easymock.EasyMock; <br />import org.easymock.IMocksControl; <br />import org.junit.Test; <br /><br />import javax.servlet.RequestDispatcher; <br />import javax.servlet.ServletContext; <br />import javax.servlet.ServletException; <br />import javax.servlet.http.HttpServletRequest; <br />import javax.servlet.http.HttpServletResponse; <br />import java.io.IOException; <br /><br />/** <br />* Created with IntelliJ IDEA. <br />* User: abin <br />* Date: 13-4-22 <br />* Time: 下午7:49 <br />* To change this template use File | Settings | File Templates. <br />*/ <br />public class EasyMockServletSuccessTest { <br />&nbsp;&nbsp;&nbsp; @Test <br />&nbsp;&nbsp;&nbsp; public void testEasyMockServletSuccess() throws ServletException, IOException { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMocksControl control= EasyMock.createControl(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request=control.createMock(HttpServletRequest.class); <br />//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response=control.createMock(HttpServletResponse.class); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ServletContext servletContext=control.createMock(ServletContext.class); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RequestDispatcher requestDispatcher=control.createMock(RequestDispatcher.class); <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expect(request.getParameter("userName")).andReturn("abin").once(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").once(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expect(servletContext.getNamedDispatcher("dispatcher")).andReturn(requestDispatcher).times(1); <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; requestDispatcher.forward(request,null); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock.expectLastCall(); <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control.replay(); <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMockServlet easyMockServlet=new EasyMockServlet(){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ServletContext getServletContext(){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return servletContext; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } ; <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; easyMockServlet.doPost(request,null); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control.verify(); <br /><br /><br />&nbsp;&nbsp;&nbsp; } <br />} <br /></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/398273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-23 13:27 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/23/398273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初学测试驱动的MOCK技术，展示一下牛逼的成果！ </title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398126.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 20 Apr 2013 07:29:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398126.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398126.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398126.html</trackback:ping><description><![CDATA[<div id="article_content" sizcache="0" sizset="33"> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">手头的项目越来越大，很多以前不会出现的问题开始浮现。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">比如：我修改了一个基础的类库，却意外的影响了九重天外的客户项目，直接导致一个功能无法实现。我郁闷啊！！！</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">因此开始要有组织、有预谋、有计划的对项目过程进行测试驱动了。最终目标是，我修改了底层某个dll的某个方法，测试框架能够自动帮我找出来所有收到影响的类，全部执行一次回归测试，并发送一份漂亮的报告到我手里。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这个目标估计1、2个星期才能实现，不过现在先放出一个非常漂亮的MOCK核心代码。&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <h1><a name="t0"></a>研究过程</h1> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">在不断收集各种资料过程中，学习了很多，例如以下关键字，有兴趣的兄弟可以自己搜索一下：</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">testdriven.net,  nunit, &nbsp;typemock, cruiseControl.net, Confluence, JIRE, NUnitForms, WatiN,  MBUnit, CSUnit, NBehave, Gallio</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">ranorex,  &nbsp;dynamicProxy...</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">估计各位有时间看看上面的简介，就能够掌握现在测试驱动的大致发展。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;"></p> <ol style="padding: 0px 0px 0px 50px; margin: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif;" sizcache="0" sizset="33"> <li style="padding-bottom: 0px; list-style-type: decimal; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">nunit的核心代码非常容易理解，大伙自己下载看看就行了。 </li><li style="padding-bottom: 0px; list-style-type: decimal; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">testdriven.net  的前身是：NUnitAddin， 如果要研究如何testdriven集成到vs，看看不错。 </li><li style="padding-bottom: 0px; list-style-type: decimal; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">WatiN的核心代码虽然我没有看，不过猜也能猜到，就是调用了IE的核，然后搜索上面的html标签操作。 </li><li style="padding-bottom: 0px; list-style-type: decimal; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" sizcache="0" sizset="33">typeMock有点混蛋，源码混淆了，无法拿到核心技术，不过从介绍来看是源自了castle.DynamicProxy，那么各位可以参观一下一篇非常垃圾的文章，但是起码让我入门了：&nbsp;<a style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; color: #3b5999; text-decoration: none; padding-top: 0px" href="http://www.cublog.cn/u/23701/showart_1414436.html" target="_blank">http://www.cublog.cn/u/23701/showart_1414436.html</a> </li><li style="padding-bottom: 0px; list-style-type: decimal; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">最后，我来到了Moq，开始因为听说是.net3.5，就没有看源码，不过刚才研究了一下顿时非常兴奋。起码Moq能让我解决了50%的工作。</li></ol> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;"></p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">接下来就说下Mock技术和测试驱动中的作用。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <h1><a name="t1"></a>Mock技术&nbsp;</h1> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">我最不喜欢老外造名词，所以会用自己的体会去介绍。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">mock的本质就是模拟目标对象的一个假对象。&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这个性质在测试驱动中非常有用，例如我的代码是：</p> <div style="margin: 5px 0px;"><img style="padding-bottom: 0px; border-width: 0px; margin: 0px; padding-left: 0px; padding-top: 0px;" id="code_img_opened_f0b263b1-61c7-4cf7-82a5-7b8ed1a645c8" alt="" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" /><span style="line-height: 1.5; margin: 0px;">代码</span>  <div style="margin: 0px;" id="cnblogs_code_open_f0b263b1-61c7-4cf7-82a5-7b8ed1a645c8"> <div style="margin: 0px;"><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;DateTime&nbsp;GetNextFiredDate(DateTime&nbsp;now,&nbsp;IOrmScheduleTrigger&nbsp;trigger,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">int</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;triggeredtimes)<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">return</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;GetNextFiredDate(now,&nbsp;trigger.TriggerType,&nbsp;trigger.TriggerExpression,&nbsp;triggeredtimes);<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div></div></div> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;现在要测试这个代码，就需要传入一个IOrmScheduleTrrigger的接口对象。但是不幸的是，这个对象是个ORM，要启动这个对象，就涉及到了数据库。。。。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">老大，我只是想测试一下一辆宝马的玻璃是否坚硬，不需要启动我的宝马加速到120km，然后再用手去翘翘那块玻璃吧。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">所以，我希望能够有个模拟对象，继承了这个接口，  同时提供了我期望的返回值，让这个方法能够顺利执行。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">传统的傻逼方法，就是自己写一个类，继承了这个接口，然后才传入进去。例如：</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <div style="margin: 5px 0px;"> <div style="margin: 0px;"><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">class</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;OrmScheduleTriggerTestObject&nbsp;:&nbsp;IOrmScheduleTrigger<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">//</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">&nbsp;some&nbsp;method&nbsp;here</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">}</span></div></div> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这样不就更加的傻逼了？我为了测一块玻璃，还亲自造了另外一台简易的宝马出来？  于是我开始翻阅各种文献，甚至考虑使用动态代理（DynamicProxy）。动态代理的核心思想就是在代码运行中写IL生成一个继承类。这个技术很有用，但是现在我还用不上（就像martin  fowler说的，typemock就等于把核武器交给了一个4岁小孩）。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">于是我继续寻找，终于翻开了Moq的源码，找到了答案。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">先看看以下一段代码，是我摘自Moq源码的核心部分，稍加改造了：</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <div style="margin: 5px 0px;" sizcache="0" sizset="34"> <div style="margin: 5px 0px 0px;" sizcache="0" sizset="34"><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 5px; padding-top: 0px" sizcache="0" sizset="34"><a style="border-bottom-style: none !important; padding-bottom: 0px; border-right-style: none !important; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-style: none !important; color: #3b5999; border-left-style: none !important; text-decoration: none; padding-top: 0px" title="复制代码" href="http://www.cnblogs.com/zc22/archive/2010/02/22/1671557.html"><img style="border-bottom-style: none !important; padding-bottom: 0px; border-right-style: none !important; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-style: none !important; border-left-style: none !important; padding-top: 0px" alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><img style="padding-bottom: 0px; border-width: 0px; margin: 0px; padding-left: 0px; padding-top: 0px;" id="code_img_opened_da58d294-f21e-4aae-8b1b-49cb8f01eb7f" alt="" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" /><span style="line-height: 1.5; margin: 0px;">代码</span>  <div style="margin: 0px;" id="cnblogs_code_open_da58d294-f21e-4aae-8b1b-49cb8f01eb7f"> <div style="margin: 0px;"><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">using</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;System;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">using</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;System.Collections.Generic;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">using</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;System.Text;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">using</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;System.Runtime.Remoting.Proxies;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">using</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;System.Runtime.Remoting.Messaging;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">namespace</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;Pixysoft.Framework.TestDrivens<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">class</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;Mock</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&lt;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">TInterface</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&gt;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;:&nbsp;RealProxy<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;Mock()<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">base</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">(</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">typeof</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">(TInterface))<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;TInterface&nbsp;Value<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">get</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">return</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;(TInterface)</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">this</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">.GetTransparentProxy();<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">override</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;IMessage&nbsp;Invoke(IMessage&nbsp;msg)<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IMethodCallMessage&nbsp;methodCall&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">=</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;msg&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">as</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;IMethodCallMessage;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">//</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">我返回int&nbsp;=&nbsp;1</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">return</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">new</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;ReturnMessage(</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #800080; padding-top: 0px">1</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">null</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #800080; padding-top: 0px">0</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">null</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">,&nbsp;methodCall);<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">interface</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;IMock<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">int</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;Devide(</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">int</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;a,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">int</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;b);<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">class</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;testrealproxy&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">//</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">测试代码在这里！！！</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">public</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">void</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;test()<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IMock&nbsp;mock&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">=</span>&nbsp;<span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #0000ff; padding-top: 0px">new</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;Mock</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&lt;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">IMock</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&gt;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">().Value;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(mock.Devide(</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #800080; padding-top: 0px">1</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">,&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #800080; padding-top: 0px">2</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">));<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">//</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px">输出&nbsp;=&nbsp;1</span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; color: #008000; padding-top: 0px"><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" /></span></div></div> <div style="margin: 5px 0px 0px;" sizcache="0" sizset="35"><span style="padding-bottom: 0px; line-height: 1.5; margin: 0px; padding-left: 0px; padding-right: 5px; padding-top: 0px" sizcache="0" sizset="35"><a style="border-bottom-style: none !important; padding-bottom: 0px; border-right-style: none !important; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-style: none !important; color: #3b5999; border-left-style: none !important; text-decoration: none; padding-top: 0px" title="复制代码" href="http://www.cnblogs.com/zc22/archive/2010/02/22/1671557.html"><img style="border-bottom-style: none !important; padding-bottom: 0px; border-right-style: none !important; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-style: none !important; border-left-style: none !important; padding-top: 0px" alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这段代码就是Moq的核心思想。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">大概意思是：我希望调用接口IMock的方法Devide，但是我压根不想写这个接口的实现。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">那么我先写一个通用的模拟对象Mock&lt;TInterface&gt;，继承了RealProxy。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">然后通过调用Value就可以返回需要的接口对象。而这个对象就是&nbsp;return  (TInterface)this.GetTransparentProxy();是个透明代理。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">最后当我调用了&nbsp;int  Devide(int a, int b); 方法的时候，等于调用了public override IMessage Invoke(IMessage  msg)方法（有点点的AOP感觉）。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <h1><a name="t2"></a>后记</h1> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">上文就是Moq的核心思想了。非常的精彩！估计有了思路，各位就可以制造自己的原子弹了。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这里插句题外话，很多人抨击重复造轮子。我就奇怪了。如果我造一个轮子花费的时间和学习用一个轮子的时间差不远，为什么不造一个？</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">而且，用别人的轮子，经常出现的情况是：很多轮子不知道挑哪个。一旦挑上了，项目进展到一般才发现不适合、有bug，于是又重头挑另外的轮子。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">这个经历是真实的。当年读大学，我的室友就是典型的挑轮子，他懂得很多框架（java），webwork，hibernate,  spring。和人砍起来朗朗上口，但是需要深入做项目了，出现问题基本上不知所措，不是翻文献，就是问师兄，最后整个项目组从来就没有一个成品。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">我自从学电脑依赖，从来就没有用过别人的轮子，即使是hibernate，我的确也没有用过，不过他的核心文档倒是看过，对比之下，和oracle的toplink相比简直就是小孩。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">比我牛逼的兄弟大有人在，希望各位牛人不要浪费自己的时间去挑别人的轮子，直接自己造一个算了。&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">最后说说接下来的工作。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">基于接口的测试驱动完成了，剩下的就是面对sealed  class 等顽固分子了， 必然需要动用非常规武器，DynamicProxy。下回再见。</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p> <p style="padding-bottom: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; padding-top: 0px;">&nbsp;</p></div> <div id="sharePanel">分享到： <a title="分享到新浪微博" name="sina" jquery1366442474843="4"></a><a title="分享到腾讯微博" name="qq" jquery1366442474843="5"></a></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/398126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-20 15:29 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/20/398126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mock方法介绍 </title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398124.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 20 Apr 2013 07:21:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398124.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398124.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398124.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398124.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398124.html</trackback:ping><description><![CDATA[<div id="article_content" sizcache="0" sizset="33"> <table style="background-color: #333333; width: 1221px; font-family: Arial; table-layout: fixed" sizcache="0" sizset="33"> <tbody sizcache="0" sizset="33"> <tr sizcache="0" sizset="33"> <td style="line-height: 18px; word-wrap: break-word; word-break: break-all; zoom: 1 !important; visibility: visible !important;" sizcache="0" sizset="33"> <div style="word-wrap: break-word; color: #dddddd; font-size: 14px; overflow: hidden; word-break: break-all; position: relative !important; zoom: 1 !important; visibility: visible !important;" id="blog_text" sizcache="0" sizset="33"> <p style="line-height: normal"><strong><span style="font-size: 24px">1&nbsp;现有的单元测试框架</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  单元测试是保证程序正确性的一种有效的测试手段，对于不同的开发语言，通常都能找到相应的单元框架。</p> <p style="line-height: normal;" sizcache="0" sizset="33"><img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/cea90e0d11879fb2ab645780.jpg" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  借助于这些单测框架的帮助，能够使得我们编写单元测试用例的过程变得便捷而优雅。框架帮我们提供了case的管理，执行，断言集，运行参数，全局事件工作，所有的这些使得我们只需关注：于对于特定的输入，被测对象的返回是否正常。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  那么，这些xUnit系列的单元测试框架是如何做到这些的了？分析这些框架，发现所有的单元测试框架都是基于以下的一种体系结构设计的。<br /><img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/08847b5add3a08de800a1889.jpg" /><br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如上图所示，单测框架中通常包括TestRunner, Test, TestResult, TestCase, TestSuite,  TestFixture六个组件。<br /><strong>TestRuner：</strong>负责驱动单元测试用例的执行，汇报测试执行的结果，从而简化测试<br /><strong>TestFixture：</strong>以测试套件的形式提供setUp()和tearDown()方法，保证两个test  case之间的执行是相互独立，互不影响的。<br /><strong>TestResult：</strong>这个组件用于收集每个test  case的执行结果<br /><strong>Test：</strong>作为TestSuite和TestCase的父类暴露run()方法为TestRunner调用<br /><strong>TestCase：</strong>暴露给用户的一个类，用户通过继承TestCase，编写自己的测试用例逻辑<br /><strong>TestSuite：</strong>提供suite功能管理testCase<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  正因为相似的体系结构，所以大多数单元测试框架都提供了类似的功能和使用方法。那么在单测中引入单元测试框架会带来什么好处，在现有单元测试框架下还会存在什么样不能解决的问题呢？<br /><strong><span style="font-size: 24px">2&nbsp;单元测试框架的优点与一些问题</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在单元测试中引入单测框架使得编写单测用例时，不需要再关注于如何驱动case的执行，如何收集结果，如何管理case集，只需要关注于如何写好单个测试用例即可；同时，在一些测试框架中通过提供丰富的断言集，公用方法，以及运行参数使得编写单个testcase的过程得到了最大的简化。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  那这其中会存在什么样的疑问了？<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  我在单元测试框架中写一个TestCase，与我单独写一个cpp文件在main()方法里写测试代码有什么本质却别吗？用了单元测试框架，并没有解决我在对复杂系统做单测时遇到的问题。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  没错，对于单个case这两者从本质上说是没有区别的。单元测试框架本身并没有告诉你如何去写TestCase，在这一点上他是没有提供任何帮助的。所以对于一些复杂的场景，只用单元测试框架是有点多少显得无能为力的。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  使用单元测试框架往往适用于以下场景的测试：单个函数，一个class，或者几个功能相关class的测试，对于纯函数测试，接口级别的测试尤其适用，如房贷计算器公式的测试。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  但是，对于一些复杂场景：<br /><em>&nbsp;被测对象依赖复杂，甚至无法简单new出这个对象<br />&nbsp;对于一些failure场景的测试<br />&nbsp;被测对象中涉及多线程合作<br />&nbsp;被测对象通过消息与外界交互的场景<br />&nbsp;&#8230;<br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  单纯依赖单测框架是无法实现单元测试的，而从某种意义上来说，这些场景反而是测试中的重点。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以分布式系统的测试为例，class 与  function级别的单元测试对整个系统的帮助不大，当然，这种单元测试对单个程序的质量有帮助；分布式系统测试的要点是测试进程间的交互：一个进程收到客户请求，该如何处理，然后转发给其他进程；收到响应之后，又修改并应答客户；同时分布式系统测试中通常更关注一些异常路径的测试，这些场景才是测试中的重点，也是难点所在。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mock方法的引入通常能帮助我们解决以上场景中遇到的难题。<br /><strong><span style="font-size: 24px">3&nbsp;Mock的引入带来了什么</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在维基百科上这样描述Mock：In object-oriented programming, mock objects are simulated  objects that mimic the behavior of real objects in controlled ways. A computer  programmer typically creates a mock object to test the behavior of some other  object, in much the same way that a car designer uses a crash test dummy to  simulate the dynamic behavior. of a human in vehicle impacts.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mock通常是指，在测试一个对象A时，我们构造一些假的对象来模拟与A之间的交互，而这些Mock对象的行为是我们事先设定且符合预期。通过这些Mock对象来测试A在正常逻辑，异常逻辑或压力情况下工作是否正常。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  引入Mock最大的优势在于：Mock的行为固定，它确保当你访问该Mock的某个方法时总是能够获得一个没有任何逻辑的直接就返回的预期结果。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mock  Object的使用通常会带来以下一些好处：<br /><em>&nbsp;隔绝其他模块出错引起本模块的测试错误。<br />&nbsp;隔绝其他模块的开发状态，只要定义好接口，不用管他们开发有没有完成。<br />&nbsp;一些速度较慢的操作，可以用Mock  Object代替，快速返回。<br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于分布式系统的测试，使用Mock  Object会有另外两项很重要的收益：<br /><em>&nbsp;通过Mock  Object可以将一些分布式测试转化为本地的测试<br />&nbsp;将Mock用于压力测试，可以解决测试集群无法模拟线上集群大规模下的压力<br /></em><strong><span style="font-size: 24px">4&nbsp;Mock的应用场景</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在使用Mock的过程中，发现Mock是有一些通用性的，对于一些应用场景，是非常适合使用Mock的：<br /><em>&nbsp;真实对象具有不可确定的行为(产生不可预测的结果，如股票的行情)<br />&nbsp;真实对象很难被创建(比如具体的web容器)<br />&nbsp;真实对象的某些行为很难触发(比如网络错误)<br />&nbsp;真实情况令程序的运行速度很慢<br />&nbsp;真实对象有用户界面<br />&nbsp;测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)<br />&nbsp;真实对象实际上并不存在(当需要和其他开发小组，或者新的硬件系统打交道的时候，这是一个普遍的问题)<br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当然，也有一些不得不Mock的场景：<br />&nbsp;<em>一些比较难构造的Object：这类Object通常有很多依赖，在单元测试中构造出这样类通常花费的成本太大。<br />&nbsp;执行操作的时间较长Object：有一些Object的操作费时，而被测对象依赖于这一个操作的执行结果，例如大文件写操作，数据的更新等等，出于测试的需求，通常将这类操作进行Mock。<br />&nbsp;异常逻辑：一些异常的逻辑往往在正常测试中是很难触发的，通过Mock可以人为的控制触发异常逻辑。<br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在一些压力测试的场景下，也不得不使用Mock，例如在分布式系统测试中，通常需要测试一些单点（如namenode，jobtracker）在压力场景下的工作是否正常。而通常测试集群在正常逻辑下无法提供足够的压力（主要原因是受限于机器数量），这时候就需要应用Mock去满足。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在这些场景下，我们应该如何去做Mock的工作了，一些现有的Mock工具可以帮助我们进行Mock工作。<br /><strong><span style="font-size: 24px">5&nbsp;Mock工具的介绍</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 手动的构造 Mock  对象通常带来额外的编码量，而且这些为创建 Mock 对象而编写的代码很有可能引入错误。目前，有许多开源项目对动态构建 Mock  对象提供了支持，这些项目能够根据现有的接口或类动态生成，这样不仅能避免额外的编码工作，同时也降低了引入错误的可能。<br />C++:&nbsp;&nbsp; GoogleMock&nbsp;  &nbsp;<a style="line-height: 20px; font-family: Tahoma; color: #86ad27; text-decoration: none" href="http://code.google.com/p/googlemock/">http://code.google.com/p/googlemock/</a></p> <p style="line-height: normal;" sizcache="0" sizset="34">Java:&nbsp;&nbsp; EasyMock&nbsp;&nbsp;&nbsp;<a style="line-height: 20px; font-family: Tahoma; color: #86ad27; text-decoration: none" href="http://easymock.org/">http://easymock.org/</a></p> <p style="line-height: normal" sizcache="0" sizset="35">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  通常Mock工具通过简单的方法对于给定的接口生成 Mock  对象的类库。它提供对接口的模拟，能够通过录制、回放、检查三步来完成大体的测试过程，可以验证方法的调用种类、次数、顺序，可以令 Mock  对象返回指定的值或抛出指定异常。通过这些Mock工具我们可以方便的构造 Mock  对象从而使单元测试顺利进行，能够应用于更加复杂的测试场景。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以EasyMock为例，通过 EasyMock，我们可以为指定的接口动态的创建  Mock 对象，并利用 Mock 对象来模拟协同模块，从而使单元测试顺利进行。这个过程大致可以划分为以下几个步骤：<br />&nbsp;<em>使用 EasyMock  生成 Mock 对象<br />&nbsp;设定 Mock 对象的预期行为和输出&nbsp;<br />&nbsp;将 Mock 对象切换到 Replay 状态<br />&nbsp;调用 Mock  对象方法进行单元测试<br />&nbsp;对 Mock 对象的行为进行验证<br /></em>EasyMock的使用和原理： &nbsp;<a style="line-height: 20px; font-family: Tahoma; color: #86ad27; text-decoration: none" href="http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/">http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/</a></p> <p style="line-height: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EasyMock 后台处理的主要原理是利用  java.lang.reflect.Proxy 为指定的接口创建一个动态代理，这个动态代理，就是我们在编码中用到的 Mock 对象。EasyMock  还为这个动态代理提供了一个 InvocationHandler  接口的实现，这个实现类的主要功能就是将动态代理的预期行为记录在某个映射表中和在实际调用时从这个映射表中取出预期输出。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  借助类似于EasyMock这样工具，大大降低了编写Mock对象的成本，通常来说Mock工具依赖于单元测试框架，为用户编写TestCase提供便利，但是本身依赖于单元测试框架去驱动，管理case，以及收集测试结果。例如EasyMock依赖于JUint，GoogleMock依赖于Gtest。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  那么有了单元测试框架和相应的Mock工具就万事俱备了，还有什么样的问题？正如单元测试框架没有告诉你如何写TestCase一样，Mock工具也没有告诉你如何去选择Mock的点。<br /><strong><span style="font-size: 24px">6&nbsp;如何选择恰当的mock点</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  对于Mock这里存在两个误区，1.是Mock的对象越多越好；2.Mock会引入巨大的工作量，通常得不偿失。这都是源于不恰当的Mock点的选取。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这里说的如何选择恰当的mock点，是说对于一个被测对象，我们应当在外围选择恰当的mock对象，以及需要mock的接口。因为对于任意一个对象，任意一段代码逻辑我们都是有办法进行Mock的，而Mock点选择直接决定了我们Mock的工作量以及测试效果。从另外一种意义上来说，不恰当Mock选择反而会对我们的测试产生误导，从而在后期的集成和系统测试中引入更多的问题。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在mock点的选择过程中，以下的一些点会是一些不错的选择<br /><em>&nbsp;网络交互：如果两个被测模块之间是通过网络进行交互的，那么对于网络交互进行Mock通常是比较合适的，如RPC<br />&nbsp;外部资源：比如文件系统、数据源，如果被测对象对此类外部资源依赖性非常强，而其行为的不可预测性很可能导致测试的随机失败，此类的外部资源也适合进行Mock。<br />&nbsp;UI：因为UI很多时候都是用户行为触发事件，系统本身只是对这些触发事件进行相应，对这类UI做Mock，往往能够实现很好的收益，很多基于关键字驱动的框架都是基于UI进行Mock的<br />&nbsp;第三方API：当接口属于使用者，通过Mock该接口来确定测试使用者与接口的交互。<br /></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当然如何做Mock一定是与被系统的特性精密关联的，一些强制性的约束和规范是不合适的。这里介绍几个做的比较好的mock的例子。<br /><strong><span style="font-size: 20px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp;杀毒软件更新部署模块的Mock</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这个例子源于一款杀毒产品的更新部署模块的测试。对于一个杀毒软件客户端而言，需要通过更新检查模块与病毒库Server进行交互，如果发现病毒库有更新则触发病毒库部署模块的最新病毒库的数据请求和部署工作，要求部署完成后杀毒软件客户端能够正常工作。<br />&nbsp;<img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/dd52a321d4723311925807ea.jpg" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  对于这一场景的测试，当时受限于这样一个条件，通常的病毒库server通常最多一天只更新一次病毒库，也就是说如果使用真实的病毒库server，那么针对更新部署模块的测试一天只能被触发一次。这是测试中所不能容忍的，通过对病毒库server进行mock可以解决这个问题。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  对于这个场景可以采取这样一种Mock方式：用一个本地文件夹来模拟病毒库server，选择更新部署模块与病毒库server之间交互的两个函数checkVersion()，reqData()函数进行Mock。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  checkVersion()工作原先的工作是检查病毒库Server的版本号，以决定是否触发更新，将其行为Mock为检查一个本地文件夹中病毒库的版本号；reqData()原有的行为是从病毒库Server拖取病毒库文件，将其Mock为从本地文件夹中拖取病毒库文件。通过这种方式我们用一个本地文件夹Mock病毒库Server的行为，其带来的产出是：我们可以随意的触发病毒库更新操作以及各种异常。通过这种方式发现了一个在更新部署过程中，病毒库Server的病毒库版本发生改变造成出错的严重bug，这个是在原有一天才触发一次更新操作的情况下永远也无法发现的。<br /><strong><span style="font-size: 20px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp;分布式系统中对NameNode模块的测试</span><br /></strong>&nbsp;<img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/032d7e057cde83927b8947e8.jpg" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在测试NameNode模块的过程中存在这样一个问题，在正常逻辑无压力条件下NameNode模块都是工作正常的。但是线上集群在大压力的情况下，是有可能触发NameNode的问题的。但是原有的测试方法下，我们是无法对NameNode模拟大压力的场景的（因为NameNode的压力主要来源于DateNode数量，而我们测试集群是远远无法达到线上几千台机器的规模的），而NameNode单点的性能瓶颈问题恰恰是测试的重点，真实的DataNode是无法满足测试需求的，我们必须对DataNode进行Mock。<br />&nbsp;<img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/134241faa96e3450d9f9fdef.jpg" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如何对DateNode进行Mock了，最直观的想法是选择NameNode与DataNode之间的交互接口进行Mock，也就是他们之间的RPC交互，但是由于NameNode与DataNode之间的交互信息种类很多，所以其实这并不是一种很好的选择。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  换个角度来想，NameNode之上的压力是源于对HDFS的读写操作造成的NameNode上元数据的维护，也就是说，对于NameNode而言，其实他并不关心数据到底写到哪里去了，只关心数据是否读写成功。如果是这种场景Mock就可以变的简单了，我们可以直接将DataNode上对块的操作进行mock，比如，对一次写请求，DataNode并不触发真实的写操作，而直接返回成功。通过这种方式，DataNode去除了执行功能，只保留了消息交互功能，间接的实现了我们的测试需求，且工作量比之第一种方案小很多。<br /><strong><span style="font-size: 20px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp;开源社区提供的MRUnit测试框架</span><br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在原有框架下，对于MapReduce程序的测试通常是无法在本地验证的，更不用说对MapReduce程序进行单测了。而MRUnit通过一个简单而优雅的Mock，却实现了一个基于MapReduce程序的单测框架。</p> <p style="line-height: normal">基于MRUINT框架可以将单测写成如下形式：</p> <p style="line-height: normal">&nbsp;<img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/6cda7b029181a84e728b65ec.jpg" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在这个框架中定义了MapDriver，ReducerDriver，MapReduceDriver三个有点类似容器的driver，通过driver来驱动map，reduce或者整个mapreduce过程的执行。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如上例，在driver中设定mapper为IdentityMapper，通过withInput方法设定输入数据，通过withOutput方法设定预期结果，通过runTest方法来触发执行并进行结果检测<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  他的实现原理是将outputCollector做Mock，outputCollectort中的emit方法实现的逻辑是将数据写到文件系统中，Mock后是通过另外一个进程去收集数据并保存在内存中，从而实现最终结果的可检验（在自己的数据结构中比对结果）。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  实现的原理很简单，这样做mock就会精巧，只选择最底层的一些简单却又依赖广泛的点（依赖广泛指模块间的数据流通常都走这样的点过）做mock，这样通常效果很好且简单<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当然这个例子中也有一些缺陷：1.因为在outputcollector层做mock的数据截取，使得无法过partition的分桶逻辑；2.这个框架是写内存的，无法最终改成压力性能测试工具。<br /></p> <p style="line-height: normal"><strong><span style="font-size: 24px">7&nbsp;附录</span><br /><span style="font-size: 20px">1.&nbsp;EasyMock示例：</span><br /></strong>&nbsp;<img style="border-bottom: #000000 1px solid; border-left: #000000 1px solid; border-top: #000000 1px solid; border-right: #000000 1px solid" border="0" alt="" src="http://hiphotos.baidu.com/baiduqa/pic/item/98f57dc8d2d76f19f21fe7e1.jpg" /><br /></p></div></td></tr></tbody></table></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/398124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-20 15:21 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/20/398124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>接口测试从零开始系列_mock技术使用 </title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398123.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 20 Apr 2013 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398123.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398123.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/20/398123.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398123.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398123.html</trackback:ping><description><![CDATA[<div id="article_content" sizcache="0" sizset="33"> <div style="line-height: 19px; font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; color: #4b4b4b; font-size: 13px" sizcache="0" sizset="33"> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"><span style="line-height: normal !important; word-break: break-all">1、什么情况下会使用mock技术</span></p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;" sizcache="0" sizset="33">　　（1）需要将当前被测单元和其依赖模块独立开来，构造一个独立的<a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" href="http://www.51testing.com/html/05/n-804105.html" target="_self">测试</a>环境，不关注被测单元的依赖对象，只关注被测单元的功能逻辑</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;" sizcache="0" sizset="34">　　----------比如被测代码中需要依赖第三方接口返回值进行逻辑处理，可能因为网络或者<a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" href="http://www.51testing.com/html/05/n-804105.html" target="_self">其他</a>环境因素，调用第三方经常会中断或者失败，无法对被测单元进行测试，这个时候就可以使用mock技术来将被测单元和依赖模块独立开来，使得测试可以进行下去。</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（2）被测单元依赖的模块尚未开发完成，而被测单元需要依赖模块的返回值进行后续处理</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　----------比如service层的代码中，包含对Dao层的调用，但是，DAO层代码尚未实现</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（3）被测单元依赖的对象较难模拟或者构造比较复杂</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　----------比如，支付宝支付的异常条件有很多，但是模拟这种异常条件很复杂或者无法模拟，比如，查询聚划算的订单结果，无法在测试环境进行模拟</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"><span style="line-height: normal !important; word-break: break-all">　　2、Mock技术分类</span></p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（1）手动构造mock对象</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　---------------比如，可以自己写某个接口方法的实现，根据需要编写返回值，测试代码中使用该实现类对象</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　缺点：会增加代码量，在写mock对象代码时，有可能引入错误</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（2）使用开源代码提供的构造mock方法</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　--------------比如easyMock，提供了对接口类的模拟，能够通过录制、回放、检查三步来完成大体的测试过程，可以验证方法的调用种类、次数、顺序，可以令Mock对象返回指定的值或抛出指定异常</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"><span style="line-height: normal !important; word-break: break-all">　　3、EasyMock使用</span></p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（1）引入easyMock</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　------------在maven工程中，通过pom配置依赖关系</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"></p> <table style="border-style: solid; border-color: #999999; background-color: #dddddd; width: 612px; font-family: Arial, Helvetica, sans-serif; color: #333333; font-size: 12px; word-break: break-all;" align="center"> <tbody style="word-break: break-all"> <tr style="word-break: break-all"> <td style="line-height: 14px; font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; word-wrap: break-word; color: #454545; word-break: break-all">&lt;dependency&gt;<br style="word-break: break-all" />&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.easymock&lt;/groupId&gt;<br style="word-break: break-all" />&nbsp;&nbsp;&nbsp;  &lt;artifactId&gt;easymock&lt;/artifactId&gt;<br style="word-break: break-all" />&nbsp;&nbsp;&nbsp; &lt;version&gt;3.0&lt;/version&gt;<br style="word-break: break-all" />&nbsp;&nbsp;&nbsp; &lt;scope&gt;test&lt;/scope&gt;<br style="word-break: break-all" />&lt;/dependency&gt;</td></tr></tbody></table> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"></p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;" sizcache="0" sizset="35">　　------------在普通<a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" href="http://www.51testing.com/html/05/n-804105.html" target="_self">java</a>工程中，通过添加外部包的方式</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（2）使用easyMock过程</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　1）使用EasyMock生成Mock对象；<br style="line-height: normal !important; word-break: break-all" />　　pingJiaDao =  mockControl.createMock(IPingJiaDao.class);</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　2）设定Mock对象的预期行为和输出；<br style="line-height: normal !important; word-break: break-all" />　　EasyMock.expect(pingJiaDao.getGoodPingJiaRate(storeId)).andReturn(0.11);</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　3）将Mock对象切换到Replay状态；<br style="line-height: normal !important; word-break: break-all" />　　EasyMock.replay(pingJiaDao);</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;" sizcache="0" sizset="36">　　4）调用Mock对象方法进行<a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" href="http://www.51testing.com/html/05/n-804105.html" target="_self">单元测试</a>；<br style="line-height: normal !important; word-break: break-all" />　　storeService.setStoredao(pingJiaDao);<br style="line-height: normal !important; word-break: break-all" />　　double rate =  storeService.getStoreGoodRate(storeId);</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　5）对Mock对象的行为进行验证。<br style="line-height: normal !important; word-break: break-all" />　　EasyMock.verify(pingJiaDao);</p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;"><span style="line-height: normal !important; word-break: break-all">　　4、其他easyMock功能</span></p> <p style="padding-bottom: 0px; margin-top: 10px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 10px; color: #333333; font-size: 12px; word-break: break-all; padding-top: 0px;">　　（1）特殊的mock对象：niceMock<br style="line-height: normal !important; word-break: break-all" />　　（2）参数匹配器<br style="line-height: normal !important; word-break: break-all" />　　（3）重置mock对象<br style="line-height: normal !important; word-break: break-all" />　　（4）模拟异常抛出<br style="line-height: normal !important; word-break: break-all" />　　（5）设置调用次数</p></div></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/398123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-20 15:19 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/20/398123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Partial]EasyMock spike</title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/10/397667.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Wed, 10 Apr 2013 14:06:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/10/397667.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/397667.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/10/397667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/397667.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/397667.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: IntroductionEasyMock (http://www.easymock.org/)使用Java的proxy机制即时为接口提供Mock Object (和扩展类的object)。因EasyMock独特的期望记录方式，大部分重构不会印象Mock Object，故EasyMock很适合于TDD。EasyMock的license为Apache 2.0&nbsp;(details see...&nbsp;&nbsp;<a href='http://www.blogjava.net/stevenjohn/archive/2013/04/10/397667.html'>阅读全文</a><img src ="http://www.blogjava.net/stevenjohn/aggbug/397667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-10 22:06 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/10/397667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EasyMock3.1  入门例子</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/27/392098.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 27 Nov 2012 14:40:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/27/392098.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/392098.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/27/392098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/392098.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/392098.html</trackback:ping><description><![CDATA[<p>//这里是测试UserDao userDao=EasyMock.createMock(UserDao.class);这种形式的：<br /><br />package com.abin.lee.mock;</p>
<p>public class User {<br />&nbsp;private int id;<br />&nbsp;private String userName;<br />&nbsp;private String passWord;<br />&nbsp;public int getId() {<br />&nbsp;&nbsp;return id;<br />&nbsp;}<br />&nbsp;public void setId(int id) {<br />&nbsp;&nbsp;this.id = id;<br />&nbsp;}<br />&nbsp;public String getUserName() {<br />&nbsp;&nbsp;return userName;<br />&nbsp;}<br />&nbsp;public void setUserName(String userName) {<br />&nbsp;&nbsp;this.userName = userName;<br />&nbsp;}<br />&nbsp;public String getPassWord() {<br />&nbsp;&nbsp;return passWord;<br />&nbsp;}<br />&nbsp;public void setPassWord(String passWord) {<br />&nbsp;&nbsp;this.passWord = passWord;<br />&nbsp;}<br />}<br /></p><br /><br /><br />
<p>package com.abin.lee.mock;</p>
<p>public interface UserDao {<br />&nbsp;User query(String id);<br />}<br /></p><br /><br /><br />
<p>package com.abin.lee.mock;</p>
<p>public class UserDaoImpl implements UserDao{</p>
<p>&nbsp;public User query(String id) {<br />&nbsp;&nbsp;User user=null;<br />&nbsp;&nbsp;if(id.equals("1")){<br />&nbsp;&nbsp;&nbsp;user=new User();<br />&nbsp;&nbsp;&nbsp;user.setId(1);<br />&nbsp;&nbsp;&nbsp;user.setUserName("abin1");<br />&nbsp;&nbsp;&nbsp;user.setPassWord("varyall1");<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;if(id.equals("2")){<br />&nbsp;&nbsp;&nbsp;user=new User();<br />&nbsp;&nbsp;&nbsp;user.setId(2);<br />&nbsp;&nbsp;&nbsp;user.setUserName("abin2");<br />&nbsp;&nbsp;&nbsp;user.setPassWord("varyall2");<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;return user;<br />&nbsp;}</p>
<p>}<br /></p><br /><br /><br /><br />
<p>package com.abin.lee.mock;</p>
<p>public interface UserService {<br />&nbsp;User query(String id);<br />}<br /></p><br /><br /><br />
<p>package com.abin.lee.mock;</p>
<p>public class UserServiceImpl implements UserService{<br />&nbsp;private UserDao userDao;<br />&nbsp;public User query(String id){<br />&nbsp;&nbsp;return this.userDao.query(id);<br />&nbsp;}<br />&nbsp;<br />&nbsp;public UserDao getUserDao() {<br />&nbsp;&nbsp;return userDao;<br />&nbsp;}</p>
<p>&nbsp;public void setUserDao(UserDao userDao) {<br />&nbsp;&nbsp;this.userDao = userDao;<br />&nbsp;}<br />&nbsp;<br />}<br /></p><br /><br /><br /><br />测试代码：<br />
<p>package com.abin.lee.mock;</p>
<p>import org.easymock.EasyMock;<br />import org.junit.Assert;<br />import org.junit.Test;</p>
<p>public class UserMock {<br />&nbsp;@Test<br />&nbsp;public void test(){<br />&nbsp;&nbsp;User expectedUser=new User();<br />&nbsp;&nbsp;expectedUser.setId(1);<br />&nbsp;&nbsp;expectedUser.setUserName("abin1");<br />&nbsp;&nbsp;expectedUser.setPassWord("varyall1");<br />&nbsp;&nbsp;UserDao userDao=EasyMock.createMock(UserDao.class);<br />&nbsp;&nbsp;EasyMock.expect(userDao.query("1")).andReturn(expectedUser);<br />&nbsp;&nbsp;EasyMock.replay(userDao);<br />&nbsp;&nbsp;UserServiceImpl service=new UserServiceImpl();<br />&nbsp;&nbsp;service.setUserDao(userDao);<br />&nbsp;&nbsp;User user=service.query("1");<br />&nbsp;&nbsp;Assert.assertNotNull(user);<br />&nbsp;&nbsp;Assert.assertEquals(1, user.getId());<br />&nbsp;&nbsp;Assert.assertEquals("abin1", user.getUserName());<br />&nbsp;&nbsp;Assert.assertEquals("varyall1", user.getPassWord());<br />&nbsp;&nbsp;EasyMock.verify(userDao);<br />&nbsp;}<br />}<br /><br /><br /><br /><br /><br />测试方法2：<br /></p>
<p>package com.abin.lee.mock;</p>
<p>import org.easymock.EasyMock;<br />import org.easymock.IMocksControl;<br />import org.junit.Assert;<br />import org.junit.Test;</p>
<p>public class UsersMock {<br />&nbsp;@Test<br />&nbsp;public void test(){<br />&nbsp;&nbsp;User expectedUser=new User();<br />&nbsp;&nbsp;expectedUser.setId(2);<br />&nbsp;&nbsp;expectedUser.setUserName("abin2");<br />&nbsp;&nbsp;expectedUser.setPassWord("varyall2");<br />&nbsp;&nbsp;IMocksControl mock=EasyMock.createNiceControl();<br />&nbsp;&nbsp;UserDao userDao=mock.createMock(UserDao.class);<br />&nbsp;&nbsp;EasyMock.expect(userDao.query("2")).andReturn(expectedUser);<br />&nbsp;&nbsp;mock.replay();<br />&nbsp;&nbsp;UserServiceImpl service=new UserServiceImpl();<br />&nbsp;&nbsp;service.setUserDao(userDao);<br />&nbsp;&nbsp;User user=service.query("2");<br />&nbsp;&nbsp;Assert.assertNotNull(user);<br />&nbsp;&nbsp;Assert.assertEquals(2, user.getId());<br />&nbsp;&nbsp;Assert.assertEquals("abin2", user.getUserName());<br />&nbsp;&nbsp;Assert.assertEquals("varyall2", user.getPassWord());<br />&nbsp;&nbsp;mock.verify();<br />&nbsp;&nbsp;mock.resetToNice();<br />&nbsp;&nbsp;<br />&nbsp;}</p>
<p>}<br /></p>
<p><br /></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/392098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-27 22:40 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/27/392098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>easyMock3.1 servlet</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/04/390765.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sun, 04 Nov 2012 14:29:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/04/390765.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/390765.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/04/390765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/390765.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/390765.html</trackback:ping><description><![CDATA[<p>package com.abin.lee.servlet.process;</p>
<p>import java.io.IOException;</p>
<p>import javax.servlet.RequestDispatcher;<br />import javax.servlet.ServletContext;<br />import javax.servlet.ServletException;<br />import javax.servlet.http.HttpServlet;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;</p>
<p>public class ProcessServlet extends HttpServlet{<br />&nbsp;public void init() throws ServletException {<br />&nbsp;&nbsp;super.init();<br />&nbsp;}<br />&nbsp;@SuppressWarnings("rawtypes")<br />&nbsp;protected void doPost(HttpServletRequest request, HttpServletResponse response)<br />&nbsp;&nbsp;&nbsp;throws ServletException, IOException {<br />&nbsp;&nbsp;String username=request.getParameter("username");<br />&nbsp;&nbsp;String password=request.getParameter("password");<br />&nbsp;&nbsp;System.out.println("username="+username);<br />&nbsp;&nbsp;System.out.println("password="+password);<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;ServletContext context = getServletContext();<br />&nbsp;&nbsp;RequestDispatcher dispatcher = context.getNamedDispatcher("dispatcher");<br />&nbsp;&nbsp;dispatcher.forward(request, response);</p>
<p><br />//&nbsp;&nbsp;ServletOutputStream out=response.getOutputStream();<br />//&nbsp;&nbsp;BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(out));<br />//&nbsp;&nbsp;writer.write("success");<br />//&nbsp;&nbsp;writer.flush();<br />//&nbsp;&nbsp;writer.close();<br />&nbsp;&nbsp;<br />&nbsp;}<br />&nbsp;public void destroy() {<br />&nbsp;&nbsp;super.destroy();<br />&nbsp;}<br />}<br /></p><br /><br /><br /><br /><br /><br /><br /><br />
<p>package com.abin.lee.servlet.process;</p>
<p>import java.io.IOException;<br />import java.io.PrintWriter;<br />import java.io.StringWriter;</p>
<p>import javax.servlet.RequestDispatcher;<br />import javax.servlet.ServletContext;<br />import javax.servlet.ServletException;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;</p>
<p>import junit.framework.TestCase;</p>
<p>import org.easymock.EasyMock;<br />import org.junit.Before;<br />import org.junit.Test;<br />public class ServletMock extends TestCase{<br />&nbsp;private static HttpServletRequest request =null;<br />&nbsp;private static HttpServletResponse response=null;<br />&nbsp;private static ServletContext context=null;<br />&nbsp;private static RequestDispatcher dispatcher=null;<br />&nbsp;private static ProcessServlet servlet=null;<br />&nbsp;@Before<br />&nbsp;public&nbsp; void setUp(){<br />&nbsp;&nbsp;request =EasyMock.createMock(HttpServletRequest.class);<br />&nbsp;&nbsp;response=EasyMock.createMock(HttpServletResponse.class);<br />&nbsp;&nbsp;context=EasyMock.createMock(ServletContext.class);<br />&nbsp;&nbsp;dispatcher=EasyMock.createMock(RequestDispatcher.class);<br />&nbsp;&nbsp;servlet=new ProcessServlet(){<br />&nbsp;&nbsp;&nbsp;private static final long serialVersionUID = 7534303474286669635L;</p>
<p>&nbsp;&nbsp;&nbsp;public ServletContext getServletContext(){<br />&nbsp;&nbsp;&nbsp;&nbsp;return context;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;};<br />&nbsp;}<br />&nbsp;@Test<br />&nbsp;public void test() throws ServletException, IOException{<br />&nbsp;&nbsp;EasyMock.expect(request.getParameter("username")).andReturn("abin").times(20000);<br />&nbsp;&nbsp;EasyMock.expect(request.getParameter("password")).andReturn("varyall").times(20000);<br />&nbsp;&nbsp;EasyMock.expectLastCall();<br />&nbsp;&nbsp;EasyMock.replay(request);<br />&nbsp;&nbsp;EasyMock.replay(response);<br />&nbsp;&nbsp;servlet.doPost(request, response);<br />&nbsp;&nbsp;EasyMock.verify(response);<br />&nbsp;&nbsp;dispatcher.forward(request, response);<br />&nbsp;&nbsp;StringWriter sw=new StringWriter();<br />&nbsp;&nbsp;PrintWriter writer=new PrintWriter(sw, true);<br />&nbsp;&nbsp;response.getOutputStream();<br />//&nbsp;&nbsp;response.set<br />//&nbsp;&nbsp;String line="";<br />//&nbsp;&nbsp;String result="";<br />//&nbsp;&nbsp;while((line=writer.)){<br />//&nbsp;&nbsp;&nbsp;<br />//&nbsp;&nbsp;}<br />//&nbsp;&nbsp;BufferedReader reader=new BufferedReader(new InputStreamReader());<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />&nbsp;}<br />}<br /></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/390765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-04 22:29 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/04/390765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>