Re: simple mock web service
- From: Chris Smith <cdsmith@xxxxxxx>
- Date: Thu, 10 Nov 2005 16:13:04 -0700
paul <paul.2.wells@xxxxxxx> wrote:
> I want to build a mock web service which intercepts call to a real web
> service; this is so that I can test the code which makes the calls with
> guaranteed results.
>
> To do this I had planned to use a very simple Servlet with a hashtable
> mapping requests to responses. As follows:
There are a couple problems worth mentioning here:
> byte[] buffer = new
> byte[request.getInputStream().available()];
> request.getInputStream().read(buffer);
As Gordon explained, this doesn't work. Actually, it doesn't work for
two reasons: first, available() may return something less than the
entire length of the request; and second, read(buffer) may read less
than the entire length of the buffer (it will return the number of bytes
read, but you throw away the return value).
However, you don't need to worry about the HTTP protocol and how it
indicates end of stream. The servlet API provides a proxy InputStream
that does signal EOF at the end of the request. This works regardless
of the underlying protocol. The underlying protocol is rather complex
(between requests with and without content-length headers, chunked
transfer encoding, etc.) so you're lucky to have the servlet API doing
this for you.
Some code that will work:
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[32768];
InputStream in = request.getInputStream();
int len;
while ((len = in.read(buffer)) != -1)
{
out.write(buffer, 0, len);
}
byte[] request = out.toByteArray();
> String requestString = new String(buffer);
Problem number two. You've just taken the input byte array, and
translated it to a String using the platform default character encoding.
You have no idea what the platform default character encoding actually
is. XML files have the encoding clearly indicated in the PI at the top
of the file, but you are ignoring it.
This bug is likely to lie dormant until something unusual happens, such
as a non-ASCII character in a String argument. When that does happen,
your code may break. Not the kind of bug you want.
Two options here:
1. Wrap the byte[] in a class that does it's own comparison. Something
like
public class ByteArrayKey
{
private byte[] val;
public ByteArrayKey(byte[] v)
{
this.val = v;
}
public boolean equals(Object other)
{
if (!(other instanceof ByteArrayKey)) return false;
ByteArrayKey k = (ByteArrayKey) other;
if (val.length != k.val.length) return false;
for (int i = 0; i < val.length; i++)
{
if (val[i] != k.val[i]) return false;
}
return true;
}
public int hashCode()
{
int result = 23;
for (int i = 0; i < val.length; i++)
{
result = result * 7 + val[i];
}
return result;
}
}
You can use this as a key in the hash table, and it's a straightforward
solution to the problem.
2. The other option is to use an XML parser, which actually will
determine the encoding marked in the input file and use it to interpret
the request as text. That's a bit more code, but it's a better answer
in the long term.
The reason is that there are innocuous differences that might exist that
change the wire representation of an XML document (such as a SOAP
request), but that don't actually change the meaning. The classic
example is:
<SomeTag></SomeTag>
<SomeTag/>
Also, whitespace inside element tags, whitespace before or after the
document element, and various other changes are not significant. Your
byte array comparison will fail if one of these fails, which means that
a perfectly acceptable change in a detail of the SOAP stub on the client
will cause your tests to fail. If you parse the XML, you reduce your
vulnerability to this situation.
Even beyond that, there are XML documents that are different at a low
level, but equivalent in the SOAP request that they express. This is
the case, for example, for differences in whitespace directly inside the
SOAP Envelope element (but after the start tag). Although that
whitespace will occur in the DOM, it is not significant in the
interpretation of the request. Also of not, changes in the aliases used
for various namespaces are not significant. Having a parsed
representation makes it much easier to recognize and ignore these
insignificant differences as well.
> However, when I try to read the input stream it is always empty. Am I
> going about this the right way? or is there an easier way of creating a
> mock web service - you would think it is a pretty common thing to need
> to do, but all of the texts I can find on it talk about interpreting
> the soap; which I don't need to do.
There might be a good reason that texts talk about interpreting SOAP.
Your approach isn't so much a test against a bug as a test against any
change. You'll find yourself spending a lot of time checking whether a
minor change is okay, and then fixing your code to accept it.
--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
.
- Follow-Ups:
- Re: simple mock web service
- From: paul
- Re: simple mock web service
- References:
- simple mock web service
- From: paul
- simple mock web service
- Prev by Date: Action listeners on different panels
- Next by Date: Re: question about coverage for java file
- Previous by thread: Re: simple mock web service
- Next by thread: Re: simple mock web service
- Index(es):
Relevant Pages
|