Я бы, вероятно, начал бы с рефакторинга кода, чтобы сделать его более слабо связанным с реальным HTTP-запросом. Прямо сейчас этот код, кажется, делает довольно много вещей.
Это можно сделать, введя абстракцию:
public interface IDataRetriever
{
public byte[] RetrieveData(byte[] request);
}
Теперь класс, который вы пытаетесь выполнить модульным тестом, можно отделить от фактического HTTP-запроса, используя шаблон проектирования Inversion of Control:
public class ClassToTest
{
private readonly IDataRetriever _dataRetriever;
public Foo(IDataRetriever dataRetriever)
{
_dataRetriever = dataRetriever;
}
public string MethodToTest(string regularExpression, string strategy)
{
string body = CreateHttpBody(regularExpression, strategy);
byte[] result = _dataRetriever.RetrieveData(Encoding.UTF8.GetBytes(body));
return ExtractResponse(Encoding.UTF8.GetString(result));
}
}
ClassToTest больше не отвечает за обработку фактического HTTP-запроса. Это теперь отделено. Тестирование MethodToTest
становится тривиальной задачей.
И последняя часть, очевидно, должна иметь реализацию введенной нами абстракции:
public class MyDataRetriever : IDataRetriever
{
private readonly string _url;
public MyDataRetriever(string url)
{
_url = url;
}
public byte[] RetrieveData(byte[] request)
{
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "text/plain; charset=utf-8";
return client.UploadData(_url, request);
}
}
}
Затем вы можете настроить вашу любимую инфраструктуру DI для внедрения экземпляра MyDataRetriever
в конструктор класса ClassToTest
в вашем реальном приложении.