2013-04-22 12 views
10

Come creare finto HttpWebRequest e HttpWebResponse oggetto Sto cercando di unittest il seguente pezzo di codiceCome creare un oggetto fittizio HttpWebRequest e 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

Quale comportamento si desidera simulare/simulare? – mellamokb

+0

aggiornato la mia domanda sopra – Steve

+0

Hai bisogno di prendere in giro quel codice? O sarebbe beffardo 'jsonResult' essere abbastanza? – Guvante

risposta

4

Non è possibile creare finto per HttpWebResponse, piuttosto che beffardo out the HttpWebResponse è una chiamata di wraping dietro un'interfaccia e prende in giro quell'interfaccia.

0

Non l'ho usato personalmente ma il framework Moles dovrebbe consentire di fare ciò che si sta tentando di fare. vedere here per un esempio che intercetta le chiamate a DateTime.Now.

2

È una vecchia domanda, ma forse può essere utile per qualcuno. Adattato da 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; 
} 

In qui si può scrivere quello che vuoi in responseObject o lasciare nulla.

0

Un HttpResponse finto potrebbe apparire come questo esempio:

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(); 
} 

On default il codice di risposta è 200, in questo caso, ma si può anche regolare con Response.StatusCode = 400;

per deridere una richiesta si può usare ad esempio uno strumento di debugger. Ad esempio il Firefox addon HttpRequester è piuttosto interessante. Puoi fare tutti i tipi di richiesta e vedrai anche la tua risposta. E 'una cosa utile direi

0

Puoi anche usare il formattatore SOAP per costruire una simulazione HttpWebRequest. Prima acquisisci la HttpWebRequest che vuoi prendere in giro come una stringa, quindi puoi personalizzarla nel test dell'unità e ricostruire HttpWebRequest deserializzando la stringa.

Ecco esempio:

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

Nel progetto ho lavorato, ho avuto bisogno di fare un po 'imperativo di un servizio ASMX Web che stava gettando errori solo nella produzione di scoprire cosa XML il servizio stava effettivamente tornando indietro. Per fare ciò, ho dovuto creare un nuovo oggetto HttpWebResponse. Il trucco base sta usando Activator.CreateInstance (che ignora il fatto che il costruttore sia deprecato). Nel mio esempio qui di seguito, sto sfruttando il fatto che stavo semplicemente clonando un oggetto HttpWebResponse esistente e reimpostando il flusso, ma la tecnica sarebbe la stessa per crearne una interamente da zero.

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

È possibile utilizzare riflessioni per riscrivere campi di risposta è necessario regolare per creare la risposta falsa. Ecco un esempio di creazione di una risposta con codice di stato 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; 
Problemi correlati