2013-04-22 5 views
10

Как создать макет HttpWebRequest и HttpWebResponse объекта Я пытаюсь UnitTest следующего фрагмента кодаКак создать макет HttpWebRequest и HttpWebResponse объекта

HttpWebrequest request; 

if (null != request) 
{       
    var response = (HttpWebResponse)request.GetResponse(); 
    using (var sr = new StreamReader(response.GetResponseStream())) 
    { 
     jsonResult = sr.ReadToEnd(); 
    } 

    var myRecords = SerializationHelper.Deserialize<Records>(jsonResult); 
} 
+0

Какое поведение вы хотите издеваться/имитировать? – mellamokb

+0

обновил мой вопрос выше – Steve

+0

Нужно ли издеваться над этим кодом? Или было бы насмехаться над 'jsonResult'? – Guvante

ответ

4

Вы не можете создать макет для HttpWebResponse, а не насмехаясь out HttpWebResponse вызывает отрыв вызова за интерфейсом и издевается над этим интерфейсом.

0

Я не использовал его лично, но рамки Moles должны позволить вам делать то, что вы пытаетесь сделать. см. here для примера, который перехватывает вызовы на DateTime.Now.

2

Это старый вопрос, но, возможно, он может быть полезен для кого-то. Взято из this question in msdn:

private static WebResponse CreateWebResponse(HttpStatusCode httpStatus, MemoryStream responseObject) 
{ 
    TcpListener l = new TcpListener(IPAddress.Loopback, 0); 
    l.Start(); 
    int port = ((IPEndPoint)l.LocalEndpoint).Port; 
    l.Stop(); 

    // Create a listener. 
    string prefix = "http://localhost:" + port + "/"; 
    HttpListener listener = new HttpListener(); 
    listener.Prefixes.Add(prefix); 
    listener.Start(); 
    try 
    { 
    listener.BeginGetContext((ar) => 
    { 
     HttpListenerContext context = listener.EndGetContext(ar); 
     HttpListenerRequest request = context.Request; 

     // Obtain a response object. 
     HttpListenerResponse response = context.Response; 

     response.StatusCode = (int)httpStatus; 

     // Construct a response. 
     if (responseObject != null) 
     { 
     byte[] buffer = responseObject.ToArray(); 

     // Get a response stream and write the response to it. 
     Stream output = response.OutputStream; 
     output.Write(buffer, 0, buffer.Length); 
     } 

     response.Close(); 
    }, null); 

    WebClient client = new WebClient(); 
    try 
    { 
     WebRequest request = WebRequest.Create(prefix); 
     request.Timeout = 30000; 
     return request.GetResponse(); 
    } 
    catch (WebException e) 
    { 
     return e.Response; 
    } 
    } 
    finally 
    { 
    listener.Stop(); 
    } 

    return null; 
} 

Здесь вы можете написать все, что вы хотите в responseObject или оставить его пустым.

0

Макет HttpResponse может выглядеть следующим образом, например:

public SenHttpMockResponse(HttpListenerContext context) 
{ 
    HttpListenerResponse response = context.Response; 
    response.Headers.Add("Content-type", @"application/json"); 
    JObject message = JObject.Parse(@"{'SomeParameterName':'ParameterValue'}"); 
    StreamWriter writer = new StreamWriter(response.OutputStream); 
    writer.Write(message); 
    writer.Close(); 
} 

По умолчанию код ответа в данном случае 200, но вы также можете настроить с Response.StatusCode = 400;

издеваться запрос можно использовать, например, инструмент отладчика. Например, Firefox addon HttpRequester довольно круто. Вы можете сделать все типы запросов, и вы тоже увидите ответ. Его удобный материал, который я бы сказал

0

Вы также можете использовать форматирование SOAP для построения ложного HttpWebRequest. Сначала захватите HttpWebRequest, который вы хотите объединить в строку, затем вы можете настроить его в своем модульном тесте и перестроить HttpWebRequest, десериализируя строку.

Вот пример:

static void Main(string[] args) 
    { 
     SoapFormatter formatter = new SoapFormatter(); 

     HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.google.com"); 
     HttpWebResponse resp = (HttpWebResponse)myReq.GetResponse(); 

     // save this soapRequest as a string and customize it for your mocking up 
     MemoryStream target = new MemoryStream(); 
     using(target) 
     { 
      formatter.Serialize(target, resp); 
     } 
     string soapRequest = Encoding.UTF8.GetString(target.GetBuffer()); 

     // now you can use the string to reconstruct the object from the string without needing anything special (other than substituting your own values into the XML) 
     HttpWebResponse myMockedObject = (HttpWebResponse)formatter.Deserialize(
      new MemoryStream(Encoding.UTF8.GetBytes(soapRequest))); 
    } 
1

В проекте я работаю, мне нужно сделать некоторые переопределение в качестве ASMX веб-сервис, который был метания ошибки только в производстве, чтобы выяснить, что XML сервис был фактически потоковым. Для этого мне пришлось создать новый объект HttpWebResponse. Основной трюк заключается в использовании Activator.CreateInstance (который обходит тот факт, что конструктор устарел). В моем примере ниже я использую тот факт, что я просто клонировал существующий объект HttpWebResponse и перезагружал поток, но техника была бы одинаковой для создания целиком с нуля.

string sLastXML; 

    public string LastXML 
    { 
     get 
     { 
      return sLastXML; 
     } 
    } 

    protected override System.Net.WebResponse GetWebResponse(System.Net.WebRequest request) 
    { 
     // Get the XML Returned 
     System.Net.HttpWebResponse oResponse = (System.Net.HttpWebResponse)request.GetResponse(); 
     System.IO.Stream oStream = oResponse.GetResponseStream(); 
     byte[] inStream = new byte[oResponse.ContentLength]; 
     int iActual = 0; 
     while (iActual < oResponse.ContentLength) 
     { 
      iActual += oStream.Read(inStream, iActual, (int)oResponse.ContentLength - iActual); 
     } 
     sLastXML = System.Text.Encoding.Default.GetString(inStream); 

     // Create new stream 
     System.IO.MemoryStream oNewStream = new System.IO.MemoryStream(); 
     oNewStream.Write(inStream, 0, (int)oResponse.ContentLength); 
     oNewStream.Position = 0; 

     // Create new response object 
     System.Net.HttpWebResponse oNewResponse = (System.Net.HttpWebResponse)System.Activator.CreateInstance(typeof(System.Net.HttpWebResponse)); 
     System.Reflection.PropertyInfo oInfo = oNewResponse.GetType().GetProperty("ResponseStream", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oInfo.SetValue(oNewResponse,oNewStream); 
     System.Reflection.FieldInfo oFInfo = oNewResponse.GetType().GetField("m_HttpResponseHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_ContentLength", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_Verb", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_StatusCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_StatusDescription", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_IsMutuallyAuthenticated", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_IsVersionHttp11", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_MediaType", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_Uri", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 
     oFInfo = oNewResponse.GetType().GetField("m_UsesProxySemantics", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy); 
     oFInfo.SetValue(oNewResponse, oFInfo.GetValue(oResponse)); 

     oNewResponse.Cookies = oResponse.Cookies; 

     return oNewResponse; 


    } 
0

Вы можете использовать отражения для переписывания полей ответа, которые необходимо настроить для создания отклика. Вот пример создания ответа с кодом состояния 429:

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
statusCode = (int)response.StatusCode; 
ActivateCallback(responseCallback, response, url, string.Empty); 

var fieldStatusCode = response.GetType().GetField("m_StatusCode", 
                BindingFlags.Public | 
                BindingFlags.NonPublic | 
                BindingFlags.Instance); 
var statusCodeNew = (HttpStatusCode)409; 
fieldStatusCode.SetValue(response, statusCodeNew); 
string responceBody = "{\"error\":{\"code\":\"AF429\",\"message\":\"Too many requests. Method=GetContents, PublisherId=00000000-0000-0000-0000-000000000000\"}}"; 

var propStream = response.GetType().GetField("m_ConnectStream", 
               BindingFlags.Public | 
               BindingFlags.NonPublic | 
               BindingFlags.Instance); 

System.IO.MemoryStream ms = new System.IO.MemoryStream(
          System.Text.Encoding.UTF8.GetBytes(responceBody)); 
propStream.SetValue(response, ms); 
ms.Position = 0; 
Смежные вопросы