Closed benson-basis closed 9 years ago
Can you give me a concrete example so I can fully understand the exact scenario.
I added a proxy to some existing unit tests of a service, and serialized the expectations. Each resulting expectation looks like the following. So, if I then deserialize and feed the results in as a request to with(), the URL is expected to match, down to the port number. So I had to write some code to reconstruct a new request with everything except the URL. Maybe that's perfectly OK, but I ended up wishing for something a bit less verbose than all those with calls to pieces of the request builder.
[ {
"httpRequest" : {
"method" : "GET",
"url" : "http://localhost:60766/raas/ping",
"path" : "/raas/ping",
"headers" : [ {
"name" : "Content-Type",
"values" : [ "*/*" ]
}, {
"name" : "Accept",
"values" : [ "application/json" ]
}, {
"name" : "User-Agent",
"values" : [ "Apache CXF 2.7.11" ]
}, {
"name" : "Cache-Control",
"values" : [ "no-cache" ]
}, {
"name" : "Pragma",
"values" : [ "no-cache" ]
}, {
"name" : "Host",
"values" : [ "localhost:60766" ]
} ]
},
"httpResponse" : {
"statusCode" : 200,
"body" : "{\"message\":\"RaaS at your service\",\"time\":1413808432181}",
"headers" : [ {
"name" : "Date",
"values" : [ "Mon, 20 Oct 2014 12:33:52 GMT" ]
}, {
"name" : "Content-Type",
"values" : [ "application/json" ]
}, {
"name" : "Server",
"values" : [ "Jetty(8.1.14.v20131031)" ]
} ]
},
"times" : {
"remainingTimes" : 1,
"unlimited" : false
}
} ]
When doing a match you only need to specify the fields which you want to match on. For example you could quite easily match the request above as follows:
{
"httpRequest" : {
"method" : "GET",
"path" : "/raas/ping"
},
"httpResponse" : {
"statusCode" : 200,
"body" : "{\"message\":\"RaaS at your service\",\"time\":1413808432181}",
"headers" : [ {
"name" : "Date",
"values" : [ "Mon, 20 Oct 2014 12:33:52 GMT" ]
}, {
"name" : "Content-Type",
"values" : [ "application/json" ]
}, {
"name" : "Server",
"values" : [ "Jetty(8.1.14.v20131031)" ]
} ]
}
}
This would then tell the MockServer any GET request with the path "/raas/ping" return the specified response. If that is not flexible enough you can also use regex in any of the string fields such as url, path or header values. This way you can make the expectation as flexible as you like.
The proxy just records what it see and dumps that out. The intention of building the proxy is that sometimes your having to mock and existing system where its not clear what all the interactions are and it is helpful to use the proxy to understand how the system behaves. So its just a guide and not specifically intended to be copy and pasted exactly into test expectations.
Does that answer help? Or did I misunderstand you problem?
I get it. I had written:
Expectation[] expectations = expectationSerializer.deserializeArray(jsonString);
for (Expectation expectation : expectations) {
HttpRequest request = expectation.getHttpRequest();
boolean get = "get".equalsIgnoreCase(request.getMethod());
/*
* The request side defines what is a match. We don't want a match on the URL;
* that will have an ephemeral port number in it. The body is an interesting
* question, leaving it here requires the client test to have just-the-same
* body, which may be unreasonable due to json serialization quirks.
* So we leave it out, and assume that we don't want to have multiple
* request-response pairs in the mock that differ only in request body.
*/
mockServerClient.when(HttpRequest.request()
.withPath(request.getPath())
.withHeaders(filterHeaders(request.getHeaders(), get))
.withMethod(request.getMethod())
.withCookies(request.getCookies())
.withQueryStringParameters(request.getQueryStringParameters()))
.respond(expectation.getHttpResponse(false));
}
and I was imagining a more concise way to say: use this serialized request, but only this much ... and, by the way, use case-insensitive matching on header names and appropriate header values.
MockServer doesn't support record and replay of expectations because from experience that leads to very brittle and expensive to support tests. If requests are recorded and replayed then they are very hard to update and over detailed. In addition often the same recorded values are shared between different tests which adds a lot of complex due to the single responsibility and encapsulation principles being broken.
However MockServer does do case in-sensitive matching of header names.
I'm going to close this issue but please re-open it if you think there is a bug or a feature request,
Fair enough.
When I deserialize the results of using the proxy to capture traffic, I end up with a completely specific URL, including the port. Could there be a with() that took an HTTP request and fuzzed it by allowing any port in the URL?