Moco mainly focuses on server configuration. There are only two kinds of API right now: Request and Response.
That means if we get the expected request and then return our response. Now, you can see a Moco reference in details.
WARNING the json configuration below is just a snippet for one pair of request and response, instead of the whole configuration file.
Moco Java API is designed in functional fashion which means you can composite any request or response easily.
server.request(and(by(uri("/target")), by(version(VERSION_1_0)))).response(with(text("foo")), header("Content-Type", "text/html"));
@Since 0.7
In all JSON APIs, you can use description to describe what is this session for. It's just used as comment, which will be ignored in runtime.
[
{
"description": "any response",
"response": {
"text": "foo"
}
}
]
@Since 0.7
If you want to response according to request content, Moco server can be configured as following:
- Java API
server.request(by("foo")).response("bar");
- JSON
{
"request" :
{
"text" : "foo"
},
"response" :
{
"text" : "bar"
}
}
If request content is too large, you can put it in a file:
- Java API
server.request(by(file("foo.request"))).response("bar");
- JSON
{
"request" :
{
"file" : "foo.request"
},
"response" :
{
"text" : "bar"
}
}
@Since 0.7
XML is a popular format for Web Services. When a request is in XML, only the XML structure is important in most cases and whitespace can be ignored. The xml
operator can be used for this case.
- Java API
server.request(xml(text("<request><parameters><id>1</id></parameters></request>"))).response("foo");
- JSON
{
"request":
{
"text":
{
"xml": "<request><parameters><id>1</id></parameters></request>"
}
},
"response":
{
"text": "foo"
}
}
NOTE: Please escape the quote in text.
The large request can be put into a file:
{
"request":
{
"file":
{
"xml": "your_file.xml"
}
},
"response":
{
"text": "foo"
}
}
@Since 0.7
For the XML/HTML request, Moco allows us to match request with XPath.
- Java API
server.request(eq(xpath("/request/parameters/id/text()"), "1")).response("bar");
- JSON
{
"request" :
{
"method" : "post",
"xpaths" :
{
"/request/parameters/id/text()" : "1"
}
},
"response" :
{
"text" : "bar"
}
}
@Since 0.7
Json is rising with RESTful style architecture. Just like XML, in the most case, only JSON structure is important, so json
operator can be used.
- Java API
server.request(json(text("{\"foo\":\"bar\"}"))).response("foo");
- JSON
{
"request":
{
"text":
{
"json": "{\"foo\":\"bar\"}"
}
},
"response":
{
"text": "foo"
}
}
NOTE: Please escape the quote in text.
@Since 0.9.2
As you have seen, it is so boring to write json with escape character, especially in json configuration. So you can try the json shortcut. The upper case could be rewritten as following:
- JSON
{
"request": {
"json": {
"foo": "bar"
}
},
"response": {
"text": "foo"
}
}
@Since 0.7
The large request can be put into a file:
- Java API
server.request(json(file("your_file.json"))).response("foo");
- JSON
{
"request":
{
"file":
{
"json": "your_file.json"
}
},
"response":
{
"text": "foo"
}
}
@Since 0.7
For the JSON/HTML request, Moco allows us to match request with JSONPath.
- Java API
server.request(eq(jsonPath("$.book[*].price"), "1")).response("response_for_json_path_request");
- JSON
{
"request":
{
"json_paths":
{
"$.book[*].price": "1"
}
},
"response":
{
"text": "response_for_json_path_request"
}
}
Moco also supports some operators which helps you write your expectation easily.
@Since 0.7
You may want to match your request with regular expression, match could be your helper:
- Java API
server.request(match(text("/\\w*/foo"))).response("bar");
- JSON
{
"request":
{
"text":
{
"match": "/\\w*/foo"
}
},
"response":
{
"text": "bar"
}
}
Moco is implemented by Java regular expression, you can refer here for more details.
@Since 0.9.2
starsWith operator can help you decide if the request information starts with a piece of text.
- Java API
server.request(startsWith(text("/foo"))).response("bar");
- JSON
{
"request":
{
"text":
{
"startsWith": "/foo"
}
},
"response":
{
"text": "bar"
}
}
@Since 0.9.2
endsWith operator can help you decide if the request information ends with a piece of text.
- Java API
server.request(endsWith(text("foo"))).response("bar");
- JSON
{
"request":
{
"text":
{
"endsWith": "foo"
}
},
"response":
{
"text": "bar"
}
}
@Since 0.9.2
contain operator helps you know whether the request information contains a piece of text.
- Java API
server.request(contain(text("foo"))).response("bar");
- JSON
{
"request":
{
"text":
{
"contain": "foo"
}
},
"response":
{
"text": "bar"
}
}
@Since 0.9.2
exist operator is used to decide whether the request information exists.
- Java API
server.request(exist(header("foo"))).response("bar");
- JSON
{
"request":
{
"headers": {
"foo": {
"exist" : "true"
}
},
"response":
{
"text": "bar"
}
}
For JSON API, you can decide whether the information does not exist.
- JSON
{
"request":
{
"headers": {
"foo": {
"exist" : "not"
}
},
"response":
{
"text": "bar"
}
}
@Since 0.7
As you have seen in previous example, response with content is pretty easy.
- Java API
server.request(by("foo")).response("bar");
- JSON
{
"request" :
{
"text" : "foo"
},
"response" :
{
"text" : "bar"
}
}
The same as request, you can response with a file if content is too large to put in a string.
- Java API
server.request(by("foo")).response(file("bar.response"));
- JSON
{
"request" :
{
"text" : "foo"
},
"response" :
{
"file" : "bar.response"
}
}
@Since 0.7
Sometimes, we need a latency to simulate slow server side operation.
- Java API
server.request(by("foo")).response(latency(5000));
- JSON
{
"request" :
{
"text" : "foo"
},
"response" :
{
"latency" : 5000
}
}
@Since 0.10.1
It's easy to setup latency with time unit.
server.response(latency(1, TimeUnit.SECONDS));
@Since 0.7
Sometimes, we want to simulate a real-world operation which change server side resource. For example:
- First time you request a resource and "foo" is returned
- We update this resource
- Again request the same URL, updated content, e.g. "bar" is expected.
We can do that by
server.request(by(text("/foo"))).response(seq("foo", "bar", "blah"));
JSON response is the API without Java API, so if response is json, we don't have to write json with escape character. Hint, json api will setup Content-Type header as well.
{
"request": {
"text": "json"
},
"response": {
"json": {
"foo" : "bar"
}
}
}
Note: Template is an experimental feature which could be changed a lot in the future. Feel free to tell how it helps or you need more features in template.
Sometimes, we need to customize our response based on something, e.g. response should have same header with request.
The goal can be reached by template:
@Since 0.8
All request content can be used in template with "req.content"
- Java
server.request(by(text("template"))).response(template("${req.content}"));
- JSON
{
"request": {
"text": "template"
},
"response": {
"text": {
"template": "${req.content}"
}
}
}
@Since 0.9.1
You can provide your own variables in your template.
- Java
server.request(by(text("template"))).response(template("${'foo'}", "foo", "bar"));
- JSON
{
"request": {
"text": "template"
},
"response": {
"text": {
"template": {
"with" : "${'foo'}",
"vars" : {
"foo" : "bar"
}
}
}
}
}
@Since 0.10.0
You can also use extractor to extract information from request.
- Java
server.request(by(text("template"))).response(template("${'foo'}", "foo", jsonPath("$.book[*].price")));
- JSON
{
"request": {
"text": "template"
},
"response": {
"text": {
"template": {
"with" : "${'foo'}",
"vars" : {
"foo" : {
"json_paths": "$.book[*].price"
}
}
}
}
}
}
Other extractors, e.g. xpath also work here.
Template can also be used in file name, thus response can be different based on different request.
- Java
server.response(file(template("${req.headers['foo'].txt")));
- JSON
[
{
"response": {
"file": {
"name": {
"template": "${req.content}.txt"
}
}
}
}
]