Mock 对象 创建高效灵活的测试用例文档格式.docx

上传人:b****2 文档编号:5227584 上传时间:2023-05-04 格式:DOCX 页数:10 大小:21.27KB
下载 相关 举报
Mock 对象 创建高效灵活的测试用例文档格式.docx_第1页
第1页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第2页
第2页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第3页
第3页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第4页
第4页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第5页
第5页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第6页
第6页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第7页
第7页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第8页
第8页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第9页
第9页 / 共10页
Mock 对象 创建高效灵活的测试用例文档格式.docx_第10页
第10页 / 共10页
亲,该文档总共10页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Mock 对象 创建高效灵活的测试用例文档格式.docx

《Mock 对象 创建高效灵活的测试用例文档格式.docx》由会员分享,可在线阅读,更多相关《Mock 对象 创建高效灵活的测试用例文档格式.docx(10页珍藏版)》请在冰点文库上搜索。

Mock 对象 创建高效灵活的测试用例文档格式.docx

通过EasyMock,开发或测试人员能够比较方便的创建Mock对象,在一定程度上减少了创建Mock对象所带来的工作量。

2.EasyMock使用示例EasyMock的使用方法和原理的详细说明请参见"

EasyMock使用方法和原理剖析"

一文。

在这里,我们仅以HttpServletRequest为例对EasyMock的功能做简单说明。

在部署到Servlet容器之前,需要和HttpServletRequest进行交互的模块可以通过构建Mock对象的方式进行单元测试。

下面是使用EasyMock(version2.3)构建Mock对象进行简单测试的例子:

publicclassHttpServletRequestUtil{

publicstaticbooleanvalidate(HttpServletRequestrequest){

Stringhost=request.getHeader("

Host"

);

returnhost.startsWith("

"

}

publicclassHttpServletRequestTestCaseextendsTestCase{

publicvoidtestHttpSevletRequest(){

HttpServletRequestmockRequest=createMock(HttpServletRequest.class);

mockRequest.getHeader("

expectLastCall().andReturn("

80"

).times

(1);

replay(mockRequest);

assertTrue(HttpServletRequestUtil.validate(mockRequest));

verify(mockRequest);

首先,我们通过EasyMock提供的静态方法createMock创建Mock对象mockRequest。

当Mock对象创建好以后,我们就可以对Mock对象的预期行为和输出进行设定。

对预期行为和输出的设定分成两个部分:

(1)对指定方法进行调用;

(2)对预期输出进行设定。

在上例中,mockRequest.getHeader("

对Mock对象的getHeader方法进行了调用,之后用expectLastCall().andReturn("

).times

(1)对Mock对象的预期输出进行了设定。

andReturn方法设定了当getHeader方法被调用时,将返回字符串"

,times方法设定了该方法预期被调用的次数是1。

在结束对Mock对象预期行为和方法的设定之后,我们可以调用replay静态方法将mockRequest对象切换成回放状态。

在回放状态下,Mock对象的方法调用将返回预先设定的输出。

在上例中,HttpServletRequestUtil类的validate方法对mockRequest的getHeader方法进行了调用,并对得到的值进行验证。

最后,我们可以用verify方法来验证预期方法的调用是否真的完成了。

假如将上例中expectLastCall().andReturn("

).times

(1)设定的调用次数修改为2,而实际测试中只调用了一次该方法,您将会看到以下的错误:

通过示例,我们了解了EasyMock的使用方法。

EasyMock能为单元测试提供了一定的便利,然而,它也有一些明显的不足之处:

测试数据和预期结果以编码的形式写在测试用例中,测试数据的任何微小变化都会导致代码的重新编译和部署;

被测试模块所包含的方法和参数硬编码在测试代码中,方法或参数的变化将导致所有相关测试代码的修改(例如HttpServletRequest中的参数经常会在开发过程中发生改变,这会影响大量测试代码);

单元测试的测试过程包含在测试代码中,当测试用例发生变化,测试代码有可能需要全部重写,造成代码的频繁修改和引入错误的机会。

3.利用XML文件配置Mock对象

为了改进目前EasyMock使用方法中存在的不足,我们需要引入配置文件来对Mock对象进行定义。

我们的目标是通过配置文件的使用来实现测试代码和数据的分离。

当开发人员由于测试用例的变化而需要改变Mock对象的测试行为时,就可以直接对配置文件作出改动,而无需修改测试代码。

构建Mock对象需要以下两方面的信息:

(1)Mock对象对应的接口或类信息;

(2)Mock对象的预期行为与输出。

如果将以上两类信息配置在文件中,通过对配置文件的解析来构造Mock对象,就可以实现测试代码和数据分离的目标,从而改进现有Mock对象构造方法中的不足。

本文在提出使用配置文件定义Mock对象这一机制的同时,也提供了一个基于EasyMock的实现。

我们将这一实现称为XMLEasyMock。

XMLEasyMock的完整实现和相关的测试代码都可以在xmleasymock.zip中找到。

如果您使用Eclipse作为IDE,那么您可以将它导入您的Workspace(如下图):

在XMLEasyMock中,我们选用XML文件作为Mock对象的配置文件,XML文件的自定义和结构特性使得它成为描述Mock对象最佳的选择。

根据以上对Mock对象信息配置的分析,我们可以给出Mock对象配置文件的模板:

?

xmlversion="

1.0"

encoding="

UTF-8"

mockConfigmockObjectsmockObjectname="

Objectname"

mockedClass="

Mockclassorinterface"

/

.

/mockObjectsmockBehaviorsmockBehaviormockObject="

method="

Expectedinvocationmethod"

paramValuesparamValuetype="

Parametertype"

value="

Parametervalue"

/paramValuesctrlOptionsctrlOptionoption="

Controloption"

Expectedreturnvalue"

times="

Expectedinvocationtimes"

/ctrlOptions

/mockBehavior

/mockBehaviors

/mockConfig

其中,mockObjects部分将配置Mock对象的生成信息,mockBehaviors部分将配置Mock对象的预期行为和输出。

印花税会计分录接下来,我们将对这两部分进行详细的说明。

根据配置文件生成Mock对象

配置文件中所包含的Mock对象生成信息包含在mockObject元素当中。

mockObject元素包含两个属性name和mockedClass,分别对应Mock对象的名称和对应的接口或类。

Mock对象的名称用于和配置文件中的其它部分相关联,而对应的接口和类用于Mock对象的生成。

ResultSet接口是每个Java开发人员都非常熟悉的接口。

以java.sql.ResultSet接口为例,为其生成一个Mock对象mockResultSet,可以在文件中配置为:

mockObjectname="

mockResultSet"

java.sql.ResultSet"

/我们可以设想一下,在EasyMock中,如果我们需要创建ResultSet接口的一个Mock对象,这个过程应当是:

IMocksControlmocksControl=EasyMock.createControl();

ResultSetmockResultSet=control.createMock(ResultSet.class);

其中,IMocksControl接口的实例mocksControl能生成并管理多个Mock对象。

在XMLEasyMock中,我们为每个Mock对象创建一个MockObject类的对象,同时用一个MockObjectController对象来管理这些Mock对象。

MockObjectController类拥有一个IMocksControl成员变量,同时提供了replay、个人所得税计算器verify和reset方法,供外部调用(如下图):

EasyMockUtil是提供给外部程序调用的工具类,loadConfig方法用于读取配置文件,findMockObjectByName方法可以通过Mock对象的变量名返回Mock对象。

配置Mock对象的预期行为

接下来我们需要配置的是Mock对象的预期行为。

Mock对象的预期行为可以简单的理解为是Mock对象方法的调用以及该方法的预期输出。

我们需要在文件中分别配置方法的预期调用和预期输出。

Mock对象的预期方法调用配置在mockBehavior元素中。

每个mockBehavior元素都包含两个属性:

mockObject和method属性。

mockObject指定该行为对应的Mock对象的名称(Mock对象必须在mockObject中定义过),method属性则指定Mock对象中预期调用的方法。

mockBehavior的子元素paramValues包含了需要配置的方法所对应的参数列表。

paramValues的每个子元素paramValue都包含两个属性:

type和value,分别指定了参数类型和参数值。

我们以ResultSet接口的Mock对象mockResultSet为例,如果我们期望对getString方法进行调用,可以配置以下信息:

在对Mock对象的方法调用进行配置以后,我们接下来对方法的预期输出进行配置。

方法的预期输出定义包含在ctrlOptions中。

ctrlOption中的option属性指定了MockControl对象在指定方法返回值时选用的选项。

Option属性可选的值包括:

其中,andReturn选项用于设定方法的预期返回值,当option属性为andReturn时,我们可以在value属性中配置方法的返回值。

在预期方法确定以后,其返回值类型也确定了,因此我们无需在此指定返回值类型。

times属性用于指定预定方法的调用次数。

如果希望为Mock对象方法设置默认的预期返回值,那么你可以选择andStubReturn,这时value属性中的返回值将作为预期方法的固定返回值,而无需多次设定。

andThrow选项用于设定预期异常抛出。

当option属性为andThrow时,value属性用于指定预期的异常类型。

times属性同样用于设定预期异常抛出的次数。

如果希望为Mock对象方法设定默认的异常抛出,您可以相应的选择andSubThrow。

如果预期方法的返回值为空(void),那么您应当指定andVoidCallable方法。

这时value属性不用设定(如果设定,XMLEasyMock会忽略该属性)。

我们仍然用ResultSet接口的getString方法为例,说明预期输出的配置效果:

以上的配置相当于在EasyMock中调用:

Myreturnvalue"

expectLastCall().andThrow(newSQLException()).times

(2);

XMLEasyMock中为每个Mock对象的预期行为创建一个MockBehavior对象。

MockBehavior类中包含了两个列表,分别包含了多个ParamValue对象和CtrlOption对象。

所有MockBehavior对象都由MockBehaviorController统一管理。

MockBehaviorController提供了loadMockBehaviors和runMockBehaviors方法,分别用于读入MockBehavior和执行预期行为设定。

这些类的关系如下图所示:

XMLEasyMock对Mock对象预期方法是通过类反射机制进行调用的。

如图4所示,当MockBehavior的runMockMethod方法被调用时,它首先通过Mock对象名查询Mock对象,接着从ParamValue中取出用户设定的参数类型和参数值。

根据Mock对象的类型、Mock对象的方法名和参数类型列表,我们可以通过Class的getDeclaredMethod获取到对应的Method对象。

最后,runModkMethod方法调用Method对象的invoke方法,完成Mock对象预期方法的调用。

在对预期方法进行调用之后,我们需要通过EasyMock类对方法的预期输出进行设定。

我们以设定预期返回值为例进行说明(设定预期异常抛出与此类似)。

如图5所示,MockBehavior类提供了runCtrlOptions用于设定方法的预期输出。

runCtrlOption方法首先调用之前得到的Method对象的getReturnType方法,获取方法的返回值类型,并将该返回值类型作为参数传递给CtrlOption的runCtrlOption方法。

runCtrlOption方法首先调用EasyMock类的expectLastCall静态方法,获得Mock对象所对应的IMocksControl实例,之后,根据预期方法的返回值类型对配置文件中的返回值进行格式化,将格式化后的数据作为参数传递给IMocksControl的andReturn方法,最后,调用times方法设定预期调用次数。

以上是XMLEasyMock对Mock对象生成、Mock对象预期行为设定的具体实现。

对于外部程序而言,只需要调用EasyMockUtil提供的loadConfig静态方法就可以达到根据配置文件构建Mock对象的目的了:

EasyMockUtil的loadConfig方法MockObjectController的loadMockObjects方法和MockBehaviorController的loadMockBehaviors方法读取和创建Mock对象及其预期行为。

MockBehaviorController的runMockBehaviors先后调用runMockMethod和runCtrlOptions方法设定Mock对象的预期方法调用和预期输出。

最后,loadConfig方法调用MockObjectControllerreplay方法将Mock对象切换成Replay状态。

4.利用Mock对象定义机制配置预期结果

在进行单元测试时,被测试模块的预期结果也编码在代码中,当测试数据或是测试用例发生变化时,预期结果也将发生改变。

我们是否能将预期结果也定义在配置文件中呢?

我们可以将被测试的对象在正确运行的情况下的行为抽象为一个Mock对象,它的预期输出,就是被测试对象在正确运行情况下的预期输出。

通过这种方式,我们就可以用类似配置Mock对象的方式对预期结果进行配置了。

在XMLEasyMock中我们提供了一个测试用的接口SalesOrder,它的实现类SalesOrderImpl的主要功能是从数据库中读取一个SalesOrder的Region和TotalPrice,并根据读取的数据计算该SalesOrder的PriceLevel:

如果我们对getPriceLevel方法进行测试,就可以将该方法在正确运行下的预期输出抽象成Mock对象,并配置如下:

mockSalesOrder"

xmleasymock.demo.test.SalesOrder"

getPriceLevel"

paramValues/

ctrlOptionsctrlOptionoption="

andReturn"

expectedresult1"

1"

ctrlOptionoption="

expectedresult2"

/mockConfig5.使用配置文件运行测试用例与在代码中动态构建Mock对象不同,XMLEasyMock是在配置文件的解析过程中动态生成Mock对象的。

因此,如果用户需要使用Mock对象,需要从解析模块中获取。

XMLEasyMock提供了一个工具类EasyMockUtil,这个工具类提供了findMockObjectByName方法用于返回Mock对象。

该方法的输入参数就是在配置文件的mockObject元素中配置的name属性。

另外,我们在上文中提到,EasyMockUtil提供了方法loadConfig用于装入配置文件,该方法的输入参数就是配置文件的路径。

在XMLEasyMock提供的测试代码(SalesOrderTestCase.java)中,我们对ResultSet接口进行了模拟,从而对SalesOrder的getPriceLevel进行测试。

在完成相关Mock对象的配置之后,我们可以通过XMLEasyMock提供的功能对测试用例实现如下:

publicclassSalesOrderTestCaseextendsTestCase{

publicvoidtestAfterConfig(){

try{

EasyMockUtil.loadConfig("

/xmleasymock/demo/properties/mockConfig.xml"

DBUtilitymockDBUtility=

(DBUtility)EasyMockUtil.findMockObjectByName("

mockDBUtility"

Connectionconn=mockDBUtility.getConnection();

Statementstmt=conn.createStatement();

ResultSetrs=stmt.executeQuery("

select*fromsales_order"

SalesOrderrealOrder=newSalesOrderImpl();

SalesOrdermockOrder=

(SalesOrder)EasyMockUtil.findMockObjectByName("

while(rs.next()){

realOrder.loadDataFromDB(rs);

assertEquals(realOrder.getPriceLevel(),mockOrder.getPriceLevel());

EasyMockUtil.verify();

}catch(Exceptione){

e.printStackTrace();

通常,在数据库连接模块中,开发人员都会开发一个类似于DBUtitlity的实现来获取数据库连接以及释放数据库资源。

在我们的测试用例中,这不是必需的,但为了对真实的开发和测试环境进行模拟,我们也在mockConfig.xml中对DBUtiltiy,Connection和Statement等接口进行了配置。

我们通过DBUtilityMock对象的名称"

获得mockDBUtility对象,并通过它得到ResultSet的Mock对象。

在对getPriceLevel方法进行测试时,我们将预期结果抽象成Mock对象,它在配置文件中的名称是mockSalesOrder。

我们通过这个名称获得预期结果的Mock对象。

最后,我们将实际结果和预期结果进行比对,从而完成测试。

6.结论

我们通过配置文件对Mock对象进行定义,实现了测试数据和代码的分离,从而避免了将数据编码在代码中所带来的一系列不便。

当测试数据或是测试用例发生变化时,开发或部署人员只需对配置文件作出改动,而不用修改测试代码和重新编译、部署,降低了测试用例发生变化所带来的工作量和时间花销。

本文基于EasyMock实现了通过配置文件定义Mock对象的机制。

初入淘宝,别让代理商毁了你的店铺

特别声明:

1:

资料来源于互联网,版权归属原作者

2:

资料内容属于网络意见,与本账号立场无关

3:

如有侵权,请告知,立即删除。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2