??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品成人久久久,yy6080久久伦理一区二区,国产色播av在线http://www.aygfsteel.com/stevenjohn/category/52961.html那些青春的岁?/description>zh-cnTue, 23 Apr 2013 08:22:04 GMTTue, 23 Apr 2013 08:22:04 GMT60EasyMock 初步学习用例Q一Q?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/stevenjohn/archive/2013/04/23/398273.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/398273.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2013/04/23/398273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/398273.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/398273.html</trackback:ping><description><![CDATA[<div id="wmqeeuq" 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 />    public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { <br />        System.out.println("doPost come in"); <br />        String userName=request.getParameter("userName"); <br />        String passWord=request.getParameter("passWord"); <br />        System.out.println("userName="+userName+",passWord="+passWord); <br />        if("abin".equals(userName)&&"varyall".equals(passWord)){ <br />            System.out.println("come in"); <br />            ServletContext context=this.getServletContext(); <br />            RequestDispatcher dispatcher=context.getNamedDispatcher("dispatcher"); <br />            dispatcher.forward(request,response); <br />        }else{ <br />            throw new RuntimeException("Login failed."); <br />        } <br />    } <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 />    @Test <br />    public void testEasyMockServletFailed(){ <br />        HttpServletRequest request=EasyMock.createMock(HttpServletRequest.class); <br />        EasyMock.expect(request.getParameter("userName")).andReturn("abin"); <br />        EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").times(1); <br />        EasyMock.replay(request); <br />        EasyMockServlet easyMockServlet=new EasyMockServlet(); <br />        try { <br />              easyMockServlet.doPost(request,null); <br />              fail("Not caught exception!"); <br />        }catch(Exception e){ <br />            assertEquals("Login failed.", e.getMessage()); <br />            e.printStackTrace(); <br />        } <br />        EasyMock.verify(request); <br />    } <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 />    @Test <br />    public void testEasyMockServletSuccess() throws ServletException, IOException { <br />        IMocksControl control= EasyMock.createControl(); <br />        HttpServletRequest request=control.createMock(HttpServletRequest.class); <br />//        HttpServletResponse response=control.createMock(HttpServletResponse.class); <br />        final ServletContext servletContext=control.createMock(ServletContext.class); <br />        RequestDispatcher requestDispatcher=control.createMock(RequestDispatcher.class); <br /><br />        EasyMock.expect(request.getParameter("userName")).andReturn("abin").once(); <br />        EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").once(); <br />        EasyMock.expect(servletContext.getNamedDispatcher("dispatcher")).andReturn(requestDispatcher).times(1); <br /><br />        requestDispatcher.forward(request,null); <br />        EasyMock.expectLastCall(); <br /><br />        control.replay(); <br /><br />        EasyMockServlet easyMockServlet=new EasyMockServlet(){ <br />           public ServletContext getServletContext(){ <br />               return servletContext; <br />           } <br />        } ; <br /><br />        easyMockServlet.doPost(request,null); <br />        control.verify(); <br /><br /><br />    } <br />} <br /></div><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/398273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2013-04-23 13:27 <a href="http://www.aygfsteel.com/stevenjohn/archive/2013/04/23/398273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初学试驱动的MOCK技术,展示一下牛逼的成果Q?http://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398126.htmlabinabinSat, 20 Apr 2013 07:29:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398126.htmlhttp://www.aygfsteel.com/stevenjohn/comments/398126.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398126.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/398126.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/398126.html

手头的项目越来越大,很多以前不会出现的问题开始Q现?/p>

 

比如Q我修改了一个基的类库,却意外的影响了九重天外的客户目Q直接导致一个功能无法实现。我郁闷啊!Q!

 

因此开始要有组l、有预谋、有计划的对目q程q行试驱动了。最l目标是Q我修改了底层某个dll的某个方法,试框架能够自动帮我扑և来所有收到媄响的c,全部执行一ơ回归测试,q发送一份漂亮的报告到我手里?/p>

 

q个目标估计1?个星期才能实玎ͼ不过现在先放Z个非常漂亮的MOCK核心代码?nbsp;

 

研究q程

在不断收集各U资料过E中Q学习了很多Q例如以下关键字Q有兴趣的兄弟可以自己搜索一下:

 

testdriven.net, nunit,  typemock, cruiseControl.net, Confluence, JIRE, NUnitForms, WatiN, MBUnit, CSUnit, NBehave, Gallio

ranorex,  dynamicProxy...

 

估计各位有时间看看上面的介,p够掌握现在测试驱动的大致发展?/p>

 

  1. nunit的核心代码非常容易理解,大伙自己下蝲看看p了?
  2. testdriven.net 的前w是QNUnitAddinQ?如果要研I如何testdriven集成到vsQ看看不错?
  3. WatiN的核心代码虽然我没有看,不过猜也能猜刎ͼ是调用了IE的核Q然后搜索上面的html标签操作?
  4. typeMock有点淯Q源码؜淆了Q无法拿到核心技术,不过从介l来看是源自了castle.DynamicProxyQ那么各位可以参观一下一非常垃圄文章Q但是v码让我入门了Q?nbsp;http://www.cublog.cn/u/23701/showart_1414436.html
  5. 最后,我来CMoqQ开始因为听说是.net3.5Q就没有看源码,不过刚才研究了一下顿旉常兴奋。v码Moq能让我解决了50%的工作?/li>

 

接下来就说下Mock技术和试驱动中的作用?/p>

 

Mock技?nbsp;

我最不喜Ƣ老外造名词,所以会用自q体会Ml?/p>

mock的本质就是模拟目标对象的一个假对象?nbsp;

q个性质在测试驱动中非常有用Q例如我的代码是Q?/p>

代码
        public DateTime GetNextFiredDate(DateTime now, IOrmScheduleTrigger trigger, int triggeredtimes)
        {
            
return GetNextFiredDate(now, trigger.TriggerType, trigger.TriggerExpression, triggeredtimes);
        }

 

 

 现在要测试这个代码,需要传入一个IOrmScheduleTrrigger的接口对象。但是不q的是,q个对象是个ORMQ要启动q个对象Q就涉及C数据库。。。?/p>

 

老大Q我只是x试一下一辆宝马的ȝ是否坚硬Q不需要启动我的宝马加速到120kmQ然后再用手ȝ那块玻璃吧?/p>

 

所以,我希望能够有个模拟对象,l承了这个接口, 同时提供了我期望的返回|让这个方法能够顺利执行?/p>

 

传统的傻逼方法,是自己写一个类Q承了q个接口Q然后才传入q去。例如:

 

public class OrmScheduleTriggerTestObject : IOrmScheduleTrigger
{
// some method here
}

 

 

q样不就更加的傻gQ我Z一块玻璃,q亲自造了另外一台简易的宝马出来Q? 于是我开始翻阅各U文献,甚至考虑使用动态代理(DynamicProxyQ。动态代理的核心思想是在代码运行中写IL生成一个承类。这个技术很有用Q但是现在我q用不上Q就像martin fowler说的Qtypemockq于把核武器交l了一?岁小孩)?/p>

 

于是我l寻找,l于d了Moq的源码,扑ֈ了答案?/p>

 

先看看以下一D代码,是我摘自Moq源码的核心部分,E加攚w了Q?/p>

 

复制代码
代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;

namespace Pixysoft.Framework.TestDrivens
{
    
public class Mock<TInterface> : RealProxy
    {
        
public Mock()
            : 
base(typeof(TInterface))
        {
        }

        
public TInterface Value
        {
            
get
            {
                
return (TInterface)this.GetTransparentProxy();
            }
        }

        
public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage methodCall 
= msg as IMethodCallMessage;

            
//我返回int = 1

            
return new ReturnMessage(1null0null, methodCall);
        }
    }

    
public interface IMock
    {
        
int Devide(int a, int b);
    }

    
public class testrealproxy //试代码在这里!Q!
    {
        
public void test()
        {
            IMock mock 
= new Mock<IMock>().Value;

            Console.WriteLine(mock.Devide(
12));

            
//输出 = 1
        }
    }
}
复制代码

 

 

q段代码是Moq的核心思想?/p>

 

大概意思是Q我希望调用接口IMock的方法DevideQ但是我压根不想写这个接口的实现?/p>

 

那么我先写一个通用的模拟对象Mock<TInterface>Q承了RealProxy?/p>

 

然后通过调用Value可以返回需要的接口对象。而这个对象就?nbsp;return (TInterface)this.GetTransparentProxy();是个透明代理?/p>

 

最后当我调用了 int Devide(int a, int b); Ҏ的时候,{于调用了public override IMessage Invoke(IMessage msg)ҎQ有点点的AOP感觉Q?/p>

 

后记

 

上文是Moq的核心思想了。非常的_ֽQ估计有了思\Q各位就可以刉自q原子弹了?/p>

 

q里插句题外话,很多人抨击重复造轮子。我奇怪了。如果我造一个轮子花费的旉和学习用一个轮子的旉差不q,Z么不造一个?

而且Q用别h的轮子,l常出现的情冉|Q很多轮子不知道挑哪个。一旦挑上了Q项目进展到一般才发现不适合、有bugQ于是又重头挑另外的轮子?/p>

 

q个l历是真实的。当q读大学Q我的室友就是典型的挑轮子,他懂得很多框ӞjavaQ,webworkQhibernate, spring。和人砍h朗朗上口Q但是需要深入做目了,出现问题基本上不知所措,不是L献,是问师兄,最后整个项目组从来没有一个成品?/p>

 

我自从学电脑依赖Q从来就没有用过别h的轮子,即是hibernateQ我的确也没有用q,不过他的核心文档倒是看过Q对比之下,和oracle的toplink相比直就是小孩?/p>

 

比我牛逼的兄弟大有人在Q希望各位牛Z要浪费自q旉L别h的轮子,直接自己造一个算了?nbsp;

 

最后说说接下来的工作?/p>

 

Z接口的测试驱动完成了Q剩下的是面对sealed class {顽固分子了Q?必然需要动用非常规武器QDynamicProxy。下回再见?/p>

 

 

分n刎ͼ


abin 2013-04-20 15:29 发表评论
]]>
MockҎ介绍 http://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398124.htmlabinabinSat, 20 Apr 2013 07:21:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398124.htmlhttp://www.aygfsteel.com/stevenjohn/comments/398124.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398124.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/398124.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/398124.html

1 现有的单元测试框?/span>
       单元试是保证程序正性的一U有效的试手段Q对于不同的开发语aQ通常都能扑ֈ相应的单元框架?/p>



       借助于这些单框架的帮助Q能够得我们编写单元测试用例的q程变得便捷而优雅。框架帮我们提供了case的管理,执行Q断a集,q行参数Q全局事g工作Q所有的q些使得我们只需xQ于对于特定的输入,被测对象的返回是否正常?br />       那么Q这些xUnitpd的单元测试框架是如何做到q些的了Q分析这些框Ӟ发现所有的单元试框架都是Z以下的一U体pȝ构设计的?br />
 
       如上图所C,单测框架中通常包括TestRunner, Test, TestResult, TestCase, TestSuite, TestFixture六个lg?br />TestRunerQ?/strong>负责驱动单元试用例的执行,汇报试执行的结果,从而简化测?br />TestFixtureQ?/strong>以测试套件的形式提供setUp()和tearDown()ҎQ保证两个test case之间的执行是怺独立Q互不媄响的?br />TestResultQ?/strong>q个lg用于攉每个test case的执行结?br />TestQ?/strong>作ؓTestSuite和TestCase的父cL露run()Ҏ为TestRunner调用
TestCaseQ?/strong>暴露l用L一个类Q用户通过l承TestCaseQ编写自q试用例逻辑
TestSuiteQ?/strong>提供suite功能理testCase
       正因为相似的体系l构Q所以大多数单元试框架都提供了cM的功能和使用Ҏ。那么在单测中引入单元测试框架会带来什么好处,在现有单元测试框架下q会存在什么样不能解决的问题呢Q?br />2 单元试框架的优点与一些问?/span>
       在单元测试中引入单测框架使得~写单测用例Ӟ不需要再x于如何驱动case的执行,如何攉l果Q如何管理case集,只需要关注于如何写好单个试用例卛_Q同Ӟ在一些测试框架中通过提供丰富的断a集,公用ҎQ以及运行参C得编写单个testcase的过E得C最大的化?br />       那这其中会存在什么样的疑问了Q?br />       我在单元试框架中写一个TestCaseQ与我单独写一个cpp文g在main()Ҏ里写试代码有什么本质却别吗Q用了单元测试框Ӟq没有解x在对复杂pȝ做单时遇到的问题?br />       没错Q对于单个caseq两者从本质上说是没有区别的。单元测试框架本wƈ没有告诉你如何去写TestCaseQ在q一点上他是没有提供M帮助的。所以对于一些复杂的场景Q只用单元测试框架是有点多少昑־无能为力的?br />       使用单元试框架往往适用于以下场景的试Q单个函敎ͼ一个classQ或者几个功能相关class的测试,对于U函数测试,接口U别的测试尤光用Q如房贷计算器公式的试?br />       但是Q对于一些复杂场景:
?em> 被测对象依赖复杂Q甚x法简单new个对?br />?nbsp;对于一些failure场景的测?br />?nbsp;被测对象中涉及多U程合作
?nbsp;被测对象通过消息与外界交互的场景
?nbsp;…
       单纯依赖单测框架是无法实现单元测试的Q而从某种意义上来_q些场景反而是试中的重点?br />       以分布式pȝ的测试ؓ例,class ? functionU别的单元测试对整个pȝ的帮助不大,当然Q这U单元测试对单个E序的质量有帮助Q分布式pȝ试的要Ҏ试q程间的交互Q一个进E收到客戯求,该如何处理,然后转发l其他进E;收到响应之后Q又修改q应{客P同时分布式系l测试中通常更关注一些异常\径的试Q这些场景才是测试中的重点,也是隄所在?br />       MockҎ的引入通常能帮助我们解决以上场景中遇到的难题?br />3 Mock的引入带来了什?/span>
       在维基百U上q样描述MockQIn 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.
       Mock通常是指Q在试一个对象AӞ我们构造一些假的对象来模拟与A之间的交互,而这些Mock对象的行为是我们事先讑֮且符合预期。通过q些Mock对象来测试A在正帔R辑Q异帔R辑或压力情况下工作是否正常?br />       引入Mock最大的优势在于QMock的行为固定,它确保当你访问该Mock的某个方法时L能够获得一个没有Q何逻辑的直接就q回的预期结果?br />       Mock Object的用通常会带来以下一些好处:
?em> 隔绝其他模块出错引v本模块的试错误?br />?nbsp;隔绝其他模块的开发状态,只要定义好接口,不用他们开发有没有完成?br />?nbsp;一些速度较慢的操作,可以用Mock Object代替Q快速返回?br />       对于分布式系l的试Q用Mock Object会有另外两项很重要的收益Q?br />?em> 通过Mock Object可以一些分布式试转化为本地的试
?nbsp;Mock用于压力试Q可以解x试集无法模拟线上集大规模下的压力
4 Mock的应用场?/span>
       在用Mock的过E中Q发现Mock是有一些通用性的Q对于一些应用场景,是非帔R合使用Mock的:
?nbsp;真实对象h不可定的行?产生不可预测的结果,如股的行情)
?nbsp;真实对象很难被创?比如具体的web容器)
?nbsp;真实对象的某些行为很难触?比如|络错误)
?nbsp;真实情况令程序的q行速度很慢
?nbsp;真实对象有用L?br />?nbsp;试需要询问真实对象它是如何被调用?比如试可能需要验证某个回调函数是否被调用?
?nbsp;真实对象实际上ƈ不存?当需要和其他开发小l,或者新的硬件系l打交道的时候,q是一个普遍的问题)
       当然Q也有一些不得不Mock的场景:
?nbsp;一些比较难构造的ObjectQ这cObject通常有很多依赖,在单元测试中构造出q样c通常p的成本太大?br />?nbsp;执行操作的时间较长ObjectQ有一些Object的操作费Ӟ而被对象依赖于q一个操作的执行l果Q例如大文g写操作,数据的更新等{,Z试的需求,通常这cL作进行Mock?br />?nbsp;异常逻辑Q一些异常的逻辑往往在正常测试中是很难触发的Q通过Mock可以Zؓ的控制触发异帔R辑?br />        在一些压力测试的场景下,也不得不使用MockQ例如在分布式系l测试中Q通常需要测试一些单点(如namenodeQjobtrackerQ在压力场景下的工作是否正常。而通常试集群在正帔R辑下无法提供够的压力Q主要原因是受限于机器数量)Q这时候就需要应用MockL?br />        在这些场景下Q我们应该如何去做Mock的工作了Q一些现有的Mock工具可以帮助我们q行Mock工作?br />5 Mock工具的介l?/span>
       手动的构?Mock 对象通常带来额外的编码量Q而且q些为创?Mock 对象而编写的代码很有可能引入错误。目前,有许多开源项目对动态构?Mock 对象提供了支持,q些目能够Ҏ现有的接口或cd态生成,q样不仅能避免额外的~码工作Q同时也降低了引入错误的可能?br />C++:   GoogleMock   http://code.google.com/p/googlemock/

Java:   EasyMock   http://easymock.org/

       通常Mock工具通过单的Ҏ对于l定的接口生?Mock 对象的类库。它提供Ҏ口的模拟Q能够通过录制、回放、检查三步来完成大体的测试过E,可以验证Ҏ的调用种cR次数、顺序,可以?Mock 对象q回指定的值或抛出指定异常。通过q些Mock工具我们可以方便的构?Mock 对象从而单元试利q行Q能够应用于更加复杂的测试场景?br />       以EasyMockZQ通过 EasyMockQ我们可以ؓ指定的接口动态的创徏 Mock 对象Qƈ利用 Mock 对象来模拟协同模块,从而单元试利q行。这个过E大致可以划分ؓ以下几个步骤Q?br />?nbsp;使用 EasyMock 生成 Mock 对象
?nbsp;讑֮ Mock 对象的预期行为和输出 
?nbsp;?Mock 对象切换?Replay 状?br />?nbsp;调用 Mock 对象Ҏq行单元试
?nbsp;?Mock 对象的行行验?br />
EasyMock的用和原理Q? http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/

       EasyMock 后台处理的主要原理是利用 java.lang.reflect.Proxy 为指定的接口创徏一个动态代理,q个动态代理,是我们在编码中用到?Mock 对象。EasyMock qؓq个动态代理提供了一?InvocationHandler 接口的实玎ͼq个实现cȝ主要功能是动态代理的预期行ؓ记录在某个映表中和在实际调用时从这个映表中取出预期输出?br />       借助cM于EasyMockq样工具Q大大降低了~写Mock对象的成本,通常来说Mock工具依赖于单元测试框Ӟ为用L写TestCase提供便利Q但是本w依赖于单元试框架去驱动,理caseQ以及收集测试结果。例如EasyMock依赖于JUintQGoogleMock依赖于Gtest?br />       那么有了单元试框架和相应的Mock工具׃事俱备了Q还有什么样的问题?正如单元试框架没有告诉你如何写TestCase一PMock工具也没有告诉你如何去选择Mock的点?br />6 如何选择恰当的mock?/span>
       对于Mockq里存在两个误区Q?.是Mock的对象越多越好;2.Mock会引入巨大的工作量,通常得不偿失。这都是源于不恰当的Mock点的选取?br />       q里说的如何选择恰当的mock点,是说对于一个被对象,我们应当在外围选择恰当的mock对象Q以及需要mock的接口。因为对于Q意一个对象,L一D代码逻辑我们都是有办法进行Mock的,而Mock炚w择直接军_了我们Mock的工作量以及试效果。从另外一U意义上来说Q不恰当Mock选择反而会Ҏ们的试产生误导Q从而在后期的集成和pȝ试中引入更多的问题?br />       在mock点的选择q程中,以下的一些点会是一些不错的选择
?em> |络交互Q如果两个被模块之间是通过|络q行交互的,那么对于|络交互q行Mock通常是比较合适的Q如RPC
?nbsp;外部资源Q比如文件系l、数据源Q如果被对象对此类外部资源依赖性非常强Q而其行ؓ的不可预性很可能D试的随机失败,此类的外部资源也适合q行Mock?br />?nbsp;UIQ因为UI很多时候都是用戯发事Ӟpȝ本n只是对这些触发事件进行相应,对这cUI做MockQ往往能够实现很好的收益,很多Z关键字驱动的框架都是ZUIq行Mock?br />?nbsp;W三方APIQ当接口属于使用者,通过Mock该接口来定试使用者与接口的交互?br />       当然如何做Mock一定是与被pȝ的特性精密关联的Q一些强制性的U束和规范是不合适的。这里介l几个做的比较好的mock的例子?br />       1. 杀毒Y件更新部|模块的Mock
       q个例子源于一ƾ杀毒品的更新部v模块的测试。对于一个杀毒Y件客L而言Q需要通过更新查模块与病毒库Serverq行交互Q如果发现病毒库有更新则触发病毒库部|模块的最新病毒库的数据请求和部v工作Q要求部|完成后杀毒Y件客L能够正常工作?br /> 

        对于q一场景的测试,当时受限于这样一个条Ӟ通常的病毒库server通常最多一天只更新一ơ病毒库Q也是说如果用真实的病毒库serverQ那么针Ҏ新部|模块的试一天只能被触发一ơ。这是测试中所不能容忍的,通过对病毒库serverq行mock可以解决q个问题?br />       对于q个场景可以采取q样一UMock方式Q用一个本地文件夹来模拟病毒库serverQ选择更新部v模块与病毒库server之间交互的两个函数checkVersion()QreqData()函数q行Mock?br />       checkVersion()工作原先的工作是查病毒库Server的版本号Q以军_是否触发更新Q将其行为Mock为检查一个本地文件夹中病毒库的版本号QreqData()原有的行为是从病毒库Server拖取病毒库文Ӟ其MockZ本地文g夹中拖取病毒库文件。通过q种方式我们用一个本地文件夹Mock病毒库Server的行为,其带来的产出是:我们可以随意的触发病毒库更新操作以及各种异常。通过q种方式发现了一个在更新部vq程中,病毒库Server的病毒库版本发生改变造成出错的严重bugQ这个是在原有一天才触发一ơ更新操作的情况下永q也无法发现的?br />       2. 分布式系l中对NameNode模块的测?/span>
 

       在测试NameNode模块的过E中存在q样一个问题,在正帔R辑无压力条件下NameNode模块都是工作正常的。但是线上集在大压力的情况下,是有可能触发NameNode的问题的。但是原有的试Ҏ下,我们是无法对NameNode模拟大压力的场景的(因ؓNameNode的压力主要来源于DateNode数量Q而我们测试集是q远无法辑ֈU上几千台机器的规模的)Q而NameNode单点的性能瓉问题恰恰是测试的重点Q真实的DataNode是无法满x试需求的Q我们必dDataNodeq行Mock?br /> 

       如何对DateNodeq行Mock了,最直观的想法是选择NameNode与DataNode之间的交互接口进行MockQ也是他们之间的RPC交互Q但是由于NameNode与DataNode之间的交互信息种cd多,所以其实这q不是一U很好的选择?br />       换个角度来想QNameNode之上的压力是源于对HDFS的读写操作造成的NameNode上元数据的维护,也就是说Q对于NameNode而言Q其实他q不兛_数据到底写到哪里MQ只兛_数据是否d成功。如果是q种场景Mock可以变的简单了Q我们可以直接将DataNode上对块的操作q行mockQ比如,对一ơ写hQDataNodeq不触发真实的写操作Q而直接返回成功。通过q种方式QDataNode去除了执行功能,只保留了消息交互功能Q间接的实现了我们的试需求,且工作量比之W一U方案小很多?br />       3. 开源社区提供的MRUnit试框架
       在原有框架下Q对于MapReduceE序的测试通常是无法在本地验证的,更不用说对MapReduceE序q行单测了。而MRUnit通过一个简单而优雅的MockQ却实现了一个基于MapReduceE序的单框架?/p>

ZMRUINT框架可以单写成如下Ş式:

 

       在这个框架中定义了MapDriverQReducerDriverQMapReduceDriver三个有点cM容器的driverQ通过driver来驱动mapQreduce或者整个mapreduceq程的执行?br />       如上例,在driver中设定mapper为IdentityMapperQ通过withInputҎ讑֮输入数据Q通过withOutputҎ讑֮预期l果Q通过runTestҎ来触发执行ƈq行l果?br />       他的实现原理是将outputCollector做MockQoutputCollectort中的emitҎ实现的逻辑是将数据写到文gpȝ中,Mock后是通过另外一个进E去攉数据q保存在内存中,从而实现最l结果的可检验(在自q数据l构中比对结果)?br />       实现的原理很单,q样做mock׃_yQ只选择最底层的一些简单却又依赖广泛的点(依赖q泛指模块间的数据流通常都走q样的点q)做mockQ这样通常效果很好且简?br />       当然q个例子中也有一些缺P1.因ؓ在outputcollector层做mock的数据截取,使得无法qpartition的分桉辑Q?.q个框架是写内存的,无法最l改成压力性能试工具?br />

7 附录
1. EasyMockCZQ?/span>
 



abin 2013-04-20 15:21 发表评论
]]>
接口试从零开始系列_mock技术?http://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398123.htmlabinabinSat, 20 Apr 2013 07:19:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398123.htmlhttp://www.aygfsteel.com/stevenjohn/comments/398123.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/20/398123.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/398123.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/398123.html

1、什么情况下会用mock技?/span>

  Q?Q需要将当前被测单元和其依赖模块独立开来,构造一个独立的环境Q不x被测单元的依赖对象,只关注被单元的功能逻辑

  ----------比如被测代码中需要依赖第三方接口q回D行逻辑处理Q可能因为网l或?a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" target="_self">其他环境因素Q调用第三方l常会中断或者失败,无法对被单元进行测试,q个时候就可以使用mock技术来被单元和依赖模块独立开来,使得试可以q行下去?/p>

  Q?Q被单元依赖的模块未开发完成,而被单元需要依赖模块的q回D行后l处?/p>

  ----------比如service层的代码中,包含对Dao层的调用Q但是,DAO层代码尚未实?/p>

  Q?Q被单元依赖的对象较难模拟或者构造比较复?/p>

  ----------比如Q支付宝支付的异常条件有很多Q但是模拟这U异常条件很复杂或者无法模拟,比如Q查询聚划算的订单结果,无法在测试环境进行模?/p>

  2、Mock技术分c?/span>

  Q?Q手动构造mock对象

  ---------------比如Q可以自己写某个接口Ҏ的实玎ͼҎ需要编写返回|试代码中用该实现cd?/p>

  ~点Q会增加代码量,在写mock对象代码Ӟ有可能引入错?/p>

  Q?Q用开源代码提供的构造mockҎ

  --------------比如easyMockQ提供了Ҏ口类的模拟,能够通过录制、回放、检查三步来完成大体的测试过E,可以验证Ҏ的调用种cR次数、顺序,可以令Mock对象q回指定的值或抛出指定异常

  3、EasyMock使用

  Q?Q引入easyMock

  ------------在maven工程中,通过pom配置依赖关系

<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>3.0</version>
    <scope>test</scope>
</dependency>

  ------------在普?a style="line-height: normal !important; color: #333333; word-break: break-all; text-decoration: none" target="_self">java工程中,通过d外部包的方式

  Q?Q用easyMockq程

  1Q用EasyMock生成Mock对象Q?br style="line-height: normal !important; word-break: break-all" />  pingJiaDao = mockControl.createMock(IPingJiaDao.class);

  2Q设定Mock对象的预期行为和输出Q?br style="line-height: normal !important; word-break: break-all" />  EasyMock.expect(pingJiaDao.getGoodPingJiaRate(storeId)).andReturn(0.11);

  3Q将Mock对象切换到Replay状态;
  EasyMock.replay(pingJiaDao);

  4Q调用Mock对象Ҏq行单元试Q?br style="line-height: normal !important; word-break: break-all" />  storeService.setStoredao(pingJiaDao);
  double rate = storeService.getStoreGoodRate(storeId);

  5Q对Mock对象的行行验证?br style="line-height: normal !important; word-break: break-all" />  EasyMock.verify(pingJiaDao);

  4、其他easyMock功能

  Q?Q特D的mock对象QniceMock
  Q?Q参数匹配器
  Q?Q重|mock对象
  Q?Q模拟异常抛?br style="line-height: normal !important; word-break: break-all" />  Q?Q设|调用次?/p>



abin 2013-04-20 15:19 发表评论
]]>
[Partial]EasyMock spikehttp://www.aygfsteel.com/stevenjohn/archive/2013/04/10/397667.htmlabinabinWed, 10 Apr 2013 14:06:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2013/04/10/397667.htmlhttp://www.aygfsteel.com/stevenjohn/comments/397667.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2013/04/10/397667.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/397667.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/397667.html阅读全文

abin 2013-04-10 22:06 发表评论
]]>
EasyMock3.1 入门例子http://www.aygfsteel.com/stevenjohn/archive/2012/11/27/392098.htmlabinabinTue, 27 Nov 2012 14:40:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/11/27/392098.htmlhttp://www.aygfsteel.com/stevenjohn/comments/392098.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/11/27/392098.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/392098.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/392098.html//q里是测试UserDao userDao=EasyMock.createMock(UserDao.class);q种形式的:

package com.abin.lee.mock;

public class User {
 private int id;
 private String userName;
 private String passWord;
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public String getPassWord() {
  return passWord;
 }
 public void setPassWord(String passWord) {
  this.passWord = passWord;
 }
}




package com.abin.lee.mock;

public interface UserDao {
 User query(String id);
}




package com.abin.lee.mock;

public class UserDaoImpl implements UserDao{

 public User query(String id) {
  User user=null;
  if(id.equals("1")){
   user=new User();
   user.setId(1);
   user.setUserName("abin1");
   user.setPassWord("varyall1");
  }
  if(id.equals("2")){
   user=new User();
   user.setId(2);
   user.setUserName("abin2");
   user.setPassWord("varyall2");
  }
  return user;
 }

}





package com.abin.lee.mock;

public interface UserService {
 User query(String id);
}




package com.abin.lee.mock;

public class UserServiceImpl implements UserService{
 private UserDao userDao;
 public User query(String id){
  return this.userDao.query(id);
 }
 
 public UserDao getUserDao() {
  return userDao;
 }

 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }
 
}





试代码Q?br />

package com.abin.lee.mock;

import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;

public class UserMock {
 @Test
 public void test(){
  User expectedUser=new User();
  expectedUser.setId(1);
  expectedUser.setUserName("abin1");
  expectedUser.setPassWord("varyall1");
  UserDao userDao=EasyMock.createMock(UserDao.class);
  EasyMock.expect(userDao.query("1")).andReturn(expectedUser);
  EasyMock.replay(userDao);
  UserServiceImpl service=new UserServiceImpl();
  service.setUserDao(userDao);
  User user=service.query("1");
  Assert.assertNotNull(user);
  Assert.assertEquals(1, user.getId());
  Assert.assertEquals("abin1", user.getUserName());
  Assert.assertEquals("varyall1", user.getPassWord());
  EasyMock.verify(userDao);
 }
}





试Ҏ2Q?br />

package com.abin.lee.mock;

import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Assert;
import org.junit.Test;

public class UsersMock {
 @Test
 public void test(){
  User expectedUser=new User();
  expectedUser.setId(2);
  expectedUser.setUserName("abin2");
  expectedUser.setPassWord("varyall2");
  IMocksControl mock=EasyMock.createNiceControl();
  UserDao userDao=mock.createMock(UserDao.class);
  EasyMock.expect(userDao.query("2")).andReturn(expectedUser);
  mock.replay();
  UserServiceImpl service=new UserServiceImpl();
  service.setUserDao(userDao);
  User user=service.query("2");
  Assert.assertNotNull(user);
  Assert.assertEquals(2, user.getId());
  Assert.assertEquals("abin2", user.getUserName());
  Assert.assertEquals("varyall2", user.getPassWord());
  mock.verify();
  mock.resetToNice();
  
 }

}




abin 2012-11-27 22:40 发表评论
]]>
easyMock3.1 servlethttp://www.aygfsteel.com/stevenjohn/archive/2012/11/04/390765.htmlabinabinSun, 04 Nov 2012 14:29:00 GMThttp://www.aygfsteel.com/stevenjohn/archive/2012/11/04/390765.htmlhttp://www.aygfsteel.com/stevenjohn/comments/390765.htmlhttp://www.aygfsteel.com/stevenjohn/archive/2012/11/04/390765.html#Feedback0http://www.aygfsteel.com/stevenjohn/comments/commentRss/390765.htmlhttp://www.aygfsteel.com/stevenjohn/services/trackbacks/390765.htmlpackage com.abin.lee.servlet.process;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ProcessServlet extends HttpServlet{
 public void init() throws ServletException {
  super.init();
 }
 @SuppressWarnings("rawtypes")
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  String username=request.getParameter("username");
  String password=request.getParameter("password");
  System.out.println("username="+username);
  System.out.println("password="+password);
  
  ServletContext context = getServletContext();
  RequestDispatcher dispatcher = context.getNamedDispatcher("dispatcher");
  dispatcher.forward(request, response);


//  ServletOutputStream out=response.getOutputStream();
//  BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(out));
//  writer.write("success");
//  writer.flush();
//  writer.close();
  
 }
 public void destroy() {
  super.destroy();
 }
}









package com.abin.lee.servlet.process;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import junit.framework.TestCase;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
public class ServletMock extends TestCase{
 private static HttpServletRequest request =null;
 private static HttpServletResponse response=null;
 private static ServletContext context=null;
 private static RequestDispatcher dispatcher=null;
 private static ProcessServlet servlet=null;
 @Before
 public  void setUp(){
  request =EasyMock.createMock(HttpServletRequest.class);
  response=EasyMock.createMock(HttpServletResponse.class);
  context=EasyMock.createMock(ServletContext.class);
  dispatcher=EasyMock.createMock(RequestDispatcher.class);
  servlet=new ProcessServlet(){
   private static final long serialVersionUID = 7534303474286669635L;

   public ServletContext getServletContext(){
    return context;
   }
  };
 }
 @Test
 public void test() throws ServletException, IOException{
  EasyMock.expect(request.getParameter("username")).andReturn("abin").times(20000);
  EasyMock.expect(request.getParameter("password")).andReturn("varyall").times(20000);
  EasyMock.expectLastCall();
  EasyMock.replay(request);
  EasyMock.replay(response);
  servlet.doPost(request, response);
  EasyMock.verify(response);
  dispatcher.forward(request, response);
  StringWriter sw=new StringWriter();
  PrintWriter writer=new PrintWriter(sw, true);
  response.getOutputStream();
//  response.set
//  String line="";
//  String result="";
//  while((line=writer.)){
//   
//  }
//  BufferedReader reader=new BufferedReader(new InputStreamReader());
  
  
  
  
 }
}



abin 2012-11-04 22:29 发表评论
]]>
վ֩ģ壺 㽭ʡ| ɽ| н| | | ӳ| | | | | | ʯ| | α| | | ī| | żҿ| | | ٲ| | ɽ| ̨| ƽ| | | | | | ɽ| ɽ| | ¡Ң| ĵ| | ϲ| | | ͼľ|