概述
Moco Runner
一、基本介绍
Moco runnner是一个基于netty实现的Http服务器模拟程序,他可以向服务器一样接受你的Http请求,并返回你所定制的响应,主要应用在单元测试和开发过程需要调用第三方接口当时第三方接口尚不可用的情况下使用。
二、快速使用
Moco主要有两种使用方式:API、单立程序单独启动。
1、API方式
引入依赖:
Maven:
<dependency>
<groupId>com.github.dreamhead</groupId>
<artifactId>moco-core</artifactId>
<version>1.0.0</version>
</dependency>
gradle:
repositories {
mavenCentral()
}
dependencies {
testCompile(
"com.github.dreamhead:moco-core:1.0.0",
)
}
API调用方式主要应用在单元测试中,以下是一个典型的应用在单元测试中的例子:
@Test
public void should_response_as_expected() throws Exception {
HttpServer server = httpServer(12306);
server.response(“foo”);
running(server, new Runnable() {
@Override
public void run() throws IOException {
Content content = Request.Get("http://localhost:12306").execute().returnContent();
assertThat(content.asString(), is("foo"));
}
});
}
以上例子创建了一个新的服务器并且做了自定义配置,随后运行单元测试,使用Apache Http Client Fluent API去请求测试服务器。在某些情况可能需要去控制服务的开启和关闭,可以在Befor注解的方法中调用相关的API,样例如下:
public class MocoRunnerTest {
private Runner runner;
@Before
public void setup() {
HttpServer server = httpServer(12306);
server.response("foo");
runner = runner(server);
runner.start();
}
@After
public void tearDown() {
runner.stop();
}
@Test
public void should_response_as_expected() throws IOException {
Content content = Request.Get("http://localhost:12306").execute().returnContent();
assertThat(content.asString(), is("foo"));
}
}
关于更多api的使用可以访问https://github.com/dreamhead/moco/tree/master/moco-doc去了解。
2、独立程序运行
首先需要下载这个程序的jar包http://central.maven.org/maven2/com/github/dreamhead/moco-runner/1.0.0/moco-runner-1.0.0-standalone.jar
像运行普通java程序一样只需要部署到服务器,执行java -jar命令就能启动,默认访问端口为12306。这种方式需要配置相应的json配置文件以达到自定有请求和响应,下面着重介绍使用方式和json配置。
在启动时就需要先配置一个JSON配置文件例子如下:
[
{
“response” :
{
“text” : “foo”
}
}
]
(foo.json)
首先要在命令启动的第一参数中指定服务器的类型,不同的服务器类型支持不同的参数:
HTTP Sever:
可以通过以下命令开启一个Http服务器:
java -jar moco-runner--standalone.jar http -p 12306 -c foo.json
其中的 是当前执行jar包的版本,-p指定访问端口,-c 指定启动时的json配置
Socket Server:
以下命令启动一个Socket server:
java -jar moco-runner-<version>-standalone.jar socket -p 12306 -c foo.json
配置文件
更改配置文件不必重启服务,服务会在热加载配置,自动检测配置的变更
可以使用-c参数指定某一个json配置文件,如果有多个配置文件,可以使用全局匹配参数,但是要确保配置文件不冲突,命令如下:
java -jar moco-runner-<version>-standalone.jar http -p 12306 -c "*.json"
端口
可以通过-p参数指定启动时的访问端口,如果没有指定端口,Moco启动时将会随机选择一个可用端口,可以在控制台看到端口信息。
全局设定
将所有的配置文件都放到一个配置文件里,但是如果想要运行很多服务在一个Moco实例时,配置文件就会变得很庞大,这种情况下,可以使用设定文件(setting.json)分离不同的文件。
下面是两个例子:
[
{
“request” : {
“uri” : “/foo”
},
“response” : {
“text” : “foo”
}
}
](foo.json)
{
“request” : {
“uri” : “/bar”
},
“response” : {
“text” : “bar”
}
}
把他们放到一个setting.json文件中及进行管理:
[
{
“include” : “foo.json”
},
{
“include” : “bar.json”
}
](setting.json)
可以使用全局设定启动一个Moco服务,命令如下:
java -jar moco-runner--standalone.jar http -p 12306 -g settings.json
注意参数是-g 而不是 上面的 -c!!!
Context
可以报一个服务的所有响应都放在一个上下文中,如下:
[
{
“context”: “/foo”,
“include”: “foo.json”
},
{
“context”: “/bar”,
“include”: “bar.json”
}
]
现在所有的foo.json里的配置都必须通过/foo访问了,访问http://localhost:12306/foo/foo, 将会获得 “foo”.访问http://localhost:12306/bar/bar会返回“bar”。
File Root 可以指定文件的根目录,以缩短配配置路径,所有同一根下的文件使用相对路径
[
{
“file_root”: “fileroot”,
“include”: “fileroot.json”
}
]
Environment
不同的环境下有不同的配置,比如,你的代码可能想要获取远程服务器代理在本地测试的时候访问模拟服务器,env将会帮助你在一个配置文件里配置所有相关的配置:
[
{
“env” : “remote”,
“include”: “foo.json”
},
{
“env” : “local”,
“include”: “bar.json”
}
](env.json)
使用命令启动不同环境的配置:
java -jar moco-runner--standalone.jar http -p 12306 -g env.json -e remote
现在当你请求的时候,所有的配置都是remote环境下的了
全局请求:
[
{
“request” : {
“headers” : {
“foo” : “bar”
}
},
“include”: “blah.json”
}
]
当你的请求带有请求头属性 “foo”:"bar"时,服务器才会有响应,在上面的例子中,响应都是blah.json里的配置,如果不带有相关请求头,会请求不到配置文件里的response。
全局响应:
[
{
“response” : {
“headers” : {
“foo” : “bar”
}
},
“include”: “blah.json”
}
]
当你发送任何请求到服务器,服务器返回的所有response带会有在header里设置"foo", “bar” 。
关闭服务
如果要关闭服务,可以通过命令或者关闭服务的端口两种方式:
关闭命令:java -jar moco-runner-<version>-standalone.jar http -p 12306 -c foo.json -s 9527
关闭端口:java -jar moco-runner-<version>-standalone.jar shutdown -s 9527
三、JSON配置文件的使用(以下的配置demo都是写在一个json文件里)
Description
在配置文件中可能需要中文注释,但是json是不能有注释的,所以Description属性就是用来专门描述用的,在运行时会被忽略,例子如下:
[
{
“description”: “any response”,
“response”: {
“text”: “foo”
}
}
]
Requst
如果想要根据请求内容返回响应,Moco server配置如下:
{
“request” :
{
“text” : “foo”
},
“response” :
{
“text” : “bar”
}
}
如果请求内容太多,还可以放在另一个文件中:
{
“request” :
{
“file” : “foo.request”
},
“response” :
{
“text” : “bar”
}
}
URL
如果你主要关注请求的url,也可以如下配置:
{
“request” :
{
“uri” : “/foo”
},
“response” :
{
“text” : “bar”
}
}
Query Parameter
有时候也,请求中带有查询参数,也可如下配置:
{
“request” :
{
“uri” : “/foo”,
“queries” :
{
“param” : “blah”
}
},
“response” :
{
“text” : “bar”
}
}
Http Method
还可以模拟请求方式 get、post、put、delete等
{
“request” :
{
“method” : “get”,
“uri” : “/foo”
},
“response” :
{
“text” : “bar”
}
}
Header
同时也可以模拟HTTP header
{
“request” :
{
“method” : “post”,
“headers” :
{
“content-type” : “application/json”
}
},
“response” :
{
“text” : “bar”
}
}
Cookie
cookie也广泛应用与开发中,当然也可以模拟
{
“request” :
{
“uri” : “/cookie”,
“cookies” :
{
“login” : “true”
}
},
“response” :
{
“text” : “success”
}
}
Form
模拟表单提交:
{
“request” :
{
“method” : “post”,
“forms” :
{
“name” : “foo”
}
},
“response” :
{
“text” : “bar”
}
}
XML
Xml是web service一种流行数据传输格式,当一个请求是xml格式时,只有xml结构会被解析,空白、空格会被忽略:
{
“request”:
{
“uri”: “/xml”,
“text”:
{
“xml”: “1”
}
},
“response”:
{
“text”: “foo”
}
}
如果请求内容过多,可以单独放在一个文件中,使用file属性引用:
{
“request”:
{
“uri”: “/xml”,
“file”:
{
“xml”: “your_file.xml”
}
},
“response”:
{
“text”: “foo”
}
}
XPath
对于XML/HTML 请求来说,Moco允许我们用XPath来匹配请求
{
“request” :
{
“method” : “post”,
“xpaths” :
{
“/request/parameters/id/text()” : “1”
}
},
“response” :
{
“text” : “bar”
}
}
JSON Request
JSON text
值得注意的是这个功能使用Jackson实现的,要确保你的POJO符合Jackson接受的格式
{
“request”:
{
“uri”: “/json”,
“text”:
{
“json”: “{“foo”:“bar”}”
}
},
“response”:
{
“text”: “foo”
}
}
JSON shortcut
注意,请在文本中转义引号,如果响应也是JSON,我们并不需要用转义字符写json文本,用转义字符写json是很繁琐的,所以可以尝试使用json 属性:
{
“request”: {
“uri”: “/json”,
“json”: {
“foo”: “bar”
}
},
“response”: {
“text”: “foo”
}
}
JSON file
内容过多的json文件可以单写在一个文件,通过以下方式引用
{
“request”:
{
“uri”: “/json”,
“file”:
{
“json”: “your_file.json”
}
},
“response”:
{
“text”: “foo”
}
}
JSONPath
对于 JSON/HTML 的请求,Moco允许用JSONPath进行匹配
{
“request”:
{
“uri”: “/jsonpath”,
“json_paths”:
{
“$.book[*].price”: “1”
}
},
“response”:
{
“text”: “response_for_json_path_request”
}
}
Operator
Moco支持一些运算符以帮助我们更容易的实现匹配需求
{
“request”:
{
“uri”:
{
“match”: “/w*/foo”
}
},
“response”:
{
“text”: “bar”
}
}
这一功能是由java的正则表达式实现的,具体参照http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
startsWith 运算符 一匹配所有某个特定开头的请求
{
“request”:
{
“uri”:
{
“startsWith”: “/foo”
}
},
“response”:
{
“text”: “bar”
}
}
endsWith则匹配结尾
{
“request”:
{
“uri”:
{
“endsWith”: “foo”
}
},
“response”:
{
“text”: “bar”
}
}
contain 匹配请求中包含指定的字符串
{
“request”:
{
“uri”:
{
“contain”: “foo”
}
},
“response”:
{
“text”: “bar”
}
}
exist 用来判定请求信息中是否存在某个字符串
{
“request”:
{
“headers”: {
“foo”: {
“exist” : “true”
}
},
“response”:
{
“text”: “bar”
}
}
也可以匹配不存在
{
“request”:
{
“headers”: {
“foo”: {
“exist” : “not”
}
},
“response”:
{
“text”: “bar”
}
}
Response
Content
先前的例子可以看到,响应内容的设置是很简单的
{
“request” :
{
“text” : “foo”
},
“response” :
{
“text” : “bar”
}
}
和request一样,如果响应的内容过的也可以单独放到一个文件中引用
{
“request” :
{
“text” : “foo”
},
“response” :
{
“file” : “bar.response”
}
}
如果想要在控制台看到正确的编码,也可以指定文件的字符集
[
{
“response”:
{
“file”:
{
“name”: “gbk.response”,
“charset”: “GBK”
}
}
}
]
字符集也可以用于路径资源
[
{
“response”:
{
“path_resource”:
{
“name”: “gbk.response”,
“charset”: “GBK”
}
}
}
]
Status Code
Moco支持状态码的模拟
{
“request” :
{
“text” : “foo”
},
“response” :
{
“status” : 200
}
}
默认情况下,response HTTP version支持request HTTP version,但是也可以自己指定自己的HTTP版本
{
“request”:
{
“uri”: “/version10”
},
“response”:
{
“version”: “HTTP/1.0”
}
}
Header
模拟指定的响应头
{
“request” :
{
“text” : “foo”
},
“response” :
{
“headers” :
{
“content-type” : “application/json”
}
}
}
Proxy
像代理一样用指定的url返回响应
{
“request” :
{
“text” : “foo”
},
“response” :
{
“proxy” : “http://www.github.com”
}
}
实际上,代理远不止这点作用,代理可以把整个请求跳转到目标url,包括HTTP method, version, header, content 等等。
除了这一基本功能,代理也支持failover,当与远程服务器暂时不可用时,Moco会从本地配置中返回一个结果
{
“request” :
{
“text” : “foo”
},
“response” :
{
“proxy” :
{
“url” : “http://localhost:12306/unknown”,
“failover” : “failover.json”
}
}
}
代理会保存request/response对 到你的 failover文件,如果代理目标不可达,代理就会从failover返回结果,这种特征对开发环境,尤其是在服务器不稳定的时候非常有用,failover是json文件,我们可以读取或者编辑我们想要的返回结果。
Playback
playback会保存远程请求和响应到本地文件,failover 和playback的差异是,palyblack只有当本地请求和响应不可用时才回去亲求远程服务器。
{
“request” :
{
“text” : “foo”
},
“response” :
{
“proxy” :
{
“url” : “http://localhost:12306/unknown”,
“playback” : “playback.json”
}
}
}
自定义 Failover/Playback 状态
可以自定义远程服务器返回哪些不可用状态时使用failover
{
“request” :
{
“text”: “foo”
},
“response” :
{
“proxy” :
{
“url” : “http://www.github.com”,
“failover” : {
“file”: “failover.json”,
“status”: [404, 500]
}
}
}
}
批量url
如果想要在上下文中用批量的url去代理,可以如下配置
{
“request” :
{
“uri” : {
“match” : “/proxy/.*”
}
},
“response” :
{
“proxy” : {
“from” : “/proxy”,
“to” : “http://localhost:12306/target”
}
}
}
failover和palyback同样可以
{
“request” :
{
“uri” : {
“match” : “/failover/.*”
}
},
“response” :
{
“proxy” :
{
“from” : “/failover”,
“to” : “http://localhost:12306/unknown”,
“failover” : “failover.response”
}
}
}
palyback
{
“request” :
{
“uri” : {
“match” : “/failover/.*”
}
},
“response” :
{
“proxy” :
{
“from” : “/failover”,
“to” : “http://localhost:12306/unknown”,
“playback” : “playback.response”
}
}
}
Redirect
重定向也在开发中普遍用到,可以简单的重定向一个请求到一个不同的url
{
“request” :
{
“uri” : “/redirect”
},
“redirectTo” : “http://www.baidu.com”
}
Cookie
cookie也能被用于响应
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : “true”
}
}
}
Cookie Attributes
cookie 属性在响应中发送,被浏览器用于决定什么时候删除cookie或者是否发送cookie到服务器
path:path属性定义了cookie的范围,需要添加path属性到你的响应中
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : {
“value” : “true”,
“path” : “/”
}
}
}
}
Domain:Domain属性定义了cookie的范围,可以在响应中添加:
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : {
“value” : “true”,
“domain” : “github.com”
}
}
}
}
Secure:一个secure cookie只能够在加密的连接中发送
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : {
“value” : “true”,
“secure” : “true”
}
}
}
}
Http only:http only cookie只能通过客户端api获取:
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : {
“value” : “true”,
“httpOnly” : “true”
}
}
}
}
max age:设置cookie的有效期
{
“request” :
{
“uri” : “/cookie”
},
“response” :
{
“cookies” :
{
“login” : {
“value” : “true”,
“maxAge”: {
“duration”: 1,
“unit”: “hour”
}
}
}
}
}
Attachment
附件也在开发中应用广泛,可以在Moco中如下配置,最好设置一个客户端接收的文件名
{
“request”: {
“uri”: “/file_attachment”
},
“response”: {
“attachment”: {
“filename”: “foo.txt”,
“file”: “foo.response”
}
}
}
Latency
有时候,我们需要模拟服务器缓慢响应的情况,可以使用这个属性,在固定时间后返回结果
{
“request” :
{
“text” : “foo”
},
“response” :
{
“latency”:
{
“duration”: 1,
“unit”: “second”
}
}
}
以上配置表明要模拟一个一秒延迟的返回
Sequence
有时候会需要模拟真是改变服务器端资源的操作,例如:
第一次请求返回“foo”资源
随后更新资源
再次请求相同的url,跟新内容变成“bar”
配置如下:
{
“request” : {
“uri” : “/seq”
},
“response”: {
“seq”: [
{
“text” : “foo”
},
{
“text” : “bar”
},
{
“text” : “blah”
}
]
}
}
Cycle
cycle和队列很想,但是他是循环的,响应返回会是循环的如
foo
bar
blah
foo
bar
blah
。。。
配置文件
{
“request” : {
“uri” : “/cycle”
},
“response”: {
“cycle”: [
{
“text” : “foo”
},
{
“text” : “bar”
},
{
“text” : “blah”
}
]
}
}
JSON Response
如果响应结果时json,我们并不需要用转义字符去写json串
{
“request”:
{
“uri”: “/json”
},
“response”:
{
“json”:
{
“foo” : “bar”
}
}
}
最后
以上就是背后乌冬面为你收集整理的Moco Runner的全部内容,希望文章能够帮你解决Moco Runner所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复