标签:
虽然静态MockOperation和MockResponse模型可以给你一定的灵活性,更多的动态行为添加到您的服务让您更模拟复杂的服务功能是很有用的。例如,你可能想:
让我们来看看如何在特定的实现这些,但我们会首先给你,你如何让你的MockServices更动态的概述。
对于MockService本身有很多可用的脚本事件:
所有这些都可以从MockService窗口:
对于MockOperations一种脚本可能是可用的; 选择“脚本”选项允许您使用决定向MockResponse返回给客户端的脚本,这样的例子
最后,对于MockResponse你可以指定一个“响应脚本”:
创建并返回给客户端的MockResponse消息之前将要执行特定的脚本的功能; 这是产生动态响应的内容主要的地方。
在soapUI中,你还可以定义项目级别的事件处理程序来指定用于运行项目中所有MockServices;
可用的模拟相关的处理程序是:
许多对象在大多数脚本通常可用:
好了,现在让我们深入的,看看这些可以用!
这是在MockResponse进行简单的脚本; 该脚本使用mockRequest对象的属性获得传入请求,通过提取的XPath所需的值,然后创建的结果写入到的RequestContext属性:
// create XmlHolder for request content
2.
def
holder =
new
com.eviware.soapui.support.XmlHolder( mockRequest.requestContent )
3.
4.
// get arguments and sum
5.
def
arg1 = Integer.parseInt( holder[
"//arg1"
] )
6.
def
arg2 = Integer.parseInt( holder[
"//arg2"
] )
7.
8.
requestContext.sum = arg1 + arg2
正如你所看到的所提取的值分配给RequestContext的(这是具体的这一要求)一个“sum”属性。:
面板左侧显示发送到我们??MockOperation最后一个请求。
这是一个比较复杂的; 我们将创建一个首先执行的soapUI的TestCase,并使用其结果来填充MockResponse消息MockResponse脚本:
// create XmlHolder for request content def holder = new com.eviware.soapui.support.XmlHolder( mockRequest.requestContent ) // get target testcase def project = mockResponse.mockOperation.mockService.project def testCase = project.testSuites["TestSuite 1"].testCases["TestCase 1"] // set arguments as properties testCase.setPropertyValue( "arg1", holder["//arg1"] ) testCase.setPropertyValue( "arg2", holder["//arg2"] ) // run testCase def runner = testCase.run( new com.eviware.soapui.support.types.StringToObjectMap(), false ) if( runner.status.toString() == "FINISHED" ) requestContext.sum = testCase.getPropertyValue( "sum" ) else requestContext.sum = "Error: " + runner.reason
该脚本首先得到保持TestCase的目标来运行,设置参数值的一些属性,然后执行它。如果一切顺利,结果从另一个TestCase的属性读取,并通过相同的机制返回,否则将显示一个错误信息。
如果我们只是本来想要执行单一请求和返回请求的响应(soapUI的转向成为一个“代理”),我们可以;
// get target request def project = mockResponse.mockOperation.mockService.project def request = project.interfaces["NewWebServicePortBinding"].operations["sum"].getRequestByName("Request 2") // set request from incoming request.requestContent = mockRequest.requestContent // submit request asynchronously request.submit( new com.eviware.soapui.impl.wsdl.WsdlSubmitContext( request ), false ) // save response to context requestContext.responseMessage = request.responseContentAsXml
在这里,我们分配整个响应到RequestContext属性; 实际MockResponse消息只是一个属性的扩展;
该脚本指定在MockOperation级,并使用与上述相同的代码以从传入的请求中提取输入值。基于某些验证它返回MockResponse的名称返回给客户端。脚本如下:
// create XmlHolder for request content def holder = new com.eviware.soapui.support.XmlHolder( mockRequest.requestContent ) // get arguments def arg1 = holder["//arg1"] def arg2 = holder["//arg2"] if( !com.eviware.soapui.support.StringUtils.hasContent( arg1 ) || !com.eviware.soapui.support.StringUtils.hasContent( arg2 )) return "Invalid Input Response" try { Integer.parseInt( arg1 ) Integer.parseInt( arg2 ) } catch( e ) { return "Invalid Input Response" } // Select valid response randomly def r = Math.random() if( r < 0.33 ) return "Simple Response" else if( r < 0.66 ) return "Call TestCase" else return "Call Request"
包含MockResponses:
在脚本中使用的RequestContext变量和我们在前面的例子中所看到的当然是一样的,让你从调度脚本传递值到MockResponse。例如,我们可以添加一个“freeMemory”属性的RequestContext:
//添加诊断 requestContext.freeMemory = Runtime.runtime.freeMemory() ...
这将使其可用于在MockOperation定义的所有MockResponses的属性扩展;
这将返回
到客户端。
这其中需要多做一些工作,因为我们需要建立和关闭数据库连接,我们可以在我们的脚本中使用。最好在MockService启动脚本做如下;
import groovy.sql.Sql // open connection def mockService = mockRunner.mockService def sql = Sql.newInstance("jdbc:mysql://" + mockService.getPropertyValue( "dbHost" ) + mockService.getPropertyValue( "dbName" ), mockService.getPropertyValue( "dbUsername" ), mockService.getPropertyValue( "dbPassword" ), "com.mysql.jdbc.Driver") log.info "Succesfully connected to database" // save to context context.dbConnection = sql
在这里,我们建立了一个连接(使用内置的数据库支持groovys‘)到配置的数据库(参数配置从MockService性质采取),然后保存在的文本中,使得它所有的脚本都是可用的。MockService停止,相应脚本关闭连接当然是需要的;
// check for connection in context if( context.dbConnection != null ) { log.info "Closing database connection" context.dbConnection.close() }
}
因此,如果我们开始和停止MockService我们将在日志中看到以下内容:
完美! 在这个具体的和简单的示例中我有一个表包含整个SOAP响应返回给客户端, 请求中的值用于查找响应返回。我选择做所有逻辑在一个单一的MockResponse脚本中:
// create XmlHolder for request content def holder = new com.eviware.soapui.support.XmlHolder( mockRequest.requestContent ) // get arguments and sum def arg1 = Integer.parseInt( holder["//arg1"] ) def arg2 = Integer.parseInt( holder["//arg2"] ) // get connection and perform query def sql = context.dbConnection def row = sql.firstRow("select * from tb_saved_messages where arg1 = ? and arg2 = ?", [arg1, arg2]) // save result to property for response requestContext.responseMessage = row.responseMessage
非常直截了当:
响应消息本身只拥有属性扩展的内容:
这将导致整个消息被写入的响应。
这是soapUI目前模拟一个REST或更复杂的HTTP服务的唯一途径; 在MockService水平OnRequest脚本,使您可以直接访问底层的HttpRequest和HttpResponse的对象允许您创建你任何喜欢的响应。所有你需要确定是否该脚本返回一个对象Mock结果告诉soapUI停止处理该请求。因此,例如,如果我们要处理,我们可以做以下PUT请求:
// check for PUT if( mockRequest.httpRequest.method == "PUT" ) { def result = new com.eviware.soapui.impl.wsdl.mock.WsdlMockResult( mockRequest ) // build path def path = mockRunner.mockService.docroot + File.separatorChar + mockRequest.httpRequest.queryString path = path.replace( (char)‘/‘, File.separatorChar ) // create File object and check if it doesnt already exists def file = new File( path ) if( !file.exists() ) { // create directories if( path.lastIndexOf( ""+File.separatorChar ) > 1 ) new File( path.substring( 0, path.lastIndexOf( ""+File.separatorChar ))).mkdirs() // write content file << mockRequest.httpRequest.inputStream mockRequest.httpResponse.status = 201 log.info "File written to [$file.absolutePath]" } else { mockRequest.httpResponse.status = 403 } return result }
正如你所看到的请求主体通过使用MockService选项对话框中的文档根目录设置的URL指定的路径;
必要的目录被创建和相应的状态代码被返回。例如http://localhost:8299/?/some/path/file.dat 与HTTP PUT和消息体将导致文件被创建。您可以使用soapUI的一个HTTP TestRequest步骤做到这一点:
而现在,因为该文件已在MockServices“文档根目录中创建你,可以用你的网页浏览器并指定http://localhost:8299/?/some/path/file.dat 将获取相应的文件。
就是这样!脚本的可能性MockServices让你轻松创建动态和“栩栩如生”的MockServices,这份文档应该让你更好地了解。祝好运!
标签:
原文地址:http://www.cnblogs.com/zerotest/p/4680940.html