I’m writing some code that calls a web service, reads back the response and does something with it. My code looks nominally like this:
string body = CreateHttpBody(regularExpression, strategy);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
request.Method = "POST";
request.ContentType = "text/plain; charset=utf-8";
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(body), 0, body.Length);
requestStream.Flush();
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
byte[] data = new byte[response.ContentLength];
using (Stream stream = response.GetResponseStream())
{
int bytesRead = 0;
while (bytesRead < data.Length)
{
bytesRead += stream.Read(data, bytesRead, data.Length - bytesRead);
}
}
return ExtractResponse(Encoding.UTF8.GetString(data));
}
The only parts where I am actually doing any custom manipulation is in the ExtractResponse and CreateHttpBody methods. However it feels wrong to just unit test those methods, and hope that the rest of the code comes together correctly. Is there any way I can intercept the HTTP request and feed it mock data instead?
EDIT This information is now out of date. It is much easier to construct this kind of code using the System.Net.Http.HttpClient libraries.
In your code you can not intercept the calls to
HttpWebRequestbecause you create the object in the same method. If you let another object create theHttpWebRequest, you can pass in a mock object and use that to test.So instead of this:
Use this:
In your unit test, you can pass in a
WebRequestFactorywhich creates a mock object.Furthermore, you can split of your stream reading code in a separate function:
This makes it possible to test
ReadStream()separately.To do more of an integration test, you can set up your own HTTP server which returns test data, and pass the URL of that server to your method.