2011-04-01 90 views
2

我们在这里有合理复杂的HTTP客户端应用程序。使用TDD证明是相当困难的。测试HttpWebRequest/HttpWebResponse客户端代码

我们开始用简单的接口:

public interface IHttp 
{ 
    TextReader RequestAndOpenTextReader(
     Uri uri, string method, TextReader body = null); 
    WebHeaderCollection RequestAndGetHeaders(
     Uri uri, string method, TextReader body = null); 
    void Request(Uri uri, string method, TextReader body = null); 
} 

但是应用需要越来越多的接触到HTTP的细节,并继续发展上述接口显得有点多余。

所以去问题。有没有方便和标准的方式来嘲讽HttpWebRequest/HttpWebResponse而不使用基于Profiler API的嘲笑框架?

或者客户端HTTP API的一些替代开源实现?

回答

0

我写了一个假的HttpWebRequest,没有太多实现它呢。它有一个参数的构造函数,所以很容易使用:

 FakeHttpWebRequest fakeHttpWebRequest = new FakeHttpWebRequest(); 
     Assert.AreEqual("application/x-www-form-urlencoded", fakeHttpWebRequest.ContentType); 

/// <summary> 
/// http://reflector.webtropy.com/default.aspx/[email protected]/[email protected]/untmp/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/Net/System/Net/[email protected]/1305376/[email protected] 
/// </summary> 
public class FakeHttpWebRequest : HttpWebRequest 
{ 
    private static readonly SerializationInfo SerializationInfo; 
    private readonly MemoryStream _requestStream; 

    static FakeHttpWebRequest() 
    { 
     SerializationInfo = new SerializationInfo(typeof(HttpWebRequest), new FormatterConverter()); 
     SerializationInfo.AddValue("_HttpRequestHeaders", new WebHeaderCollection(), typeof(WebHeaderCollection)); 
     SerializationInfo.AddValue("_Proxy", null, typeof(IWebProxy)); 
     SerializationInfo.AddValue("_KeepAlive", false); 
     SerializationInfo.AddValue("_Pipelined", false); 
     SerializationInfo.AddValue("_AllowAutoRedirect", false); 
     SerializationInfo.AddValue("_AllowWriteStreamBuffering", false); 
     SerializationInfo.AddValue("_HttpWriteMode", 0); 
     SerializationInfo.AddValue("_MaximumAllowedRedirections", 0); 
     SerializationInfo.AddValue("_AutoRedirects", 0); 
     SerializationInfo.AddValue("_Timeout", 500); 
     SerializationInfo.AddValue("_ReadWriteTimeout", 500); 
     SerializationInfo.AddValue("_MaximumResponseHeadersLength", 128); 
     SerializationInfo.AddValue("_ContentLength", 0); 
     SerializationInfo.AddValue("_MediaType", 0); 
     SerializationInfo.AddValue("_OriginVerb", 0); 
     SerializationInfo.AddValue("_ConnectionGroupName", null); 
     SerializationInfo.AddValue("_Version", HttpVersion.Version11, typeof(Version)); 
     SerializationInfo.AddValue("_OriginUri", new Uri("http://test.se"), typeof(Uri)); 

     serializationInfo.AddValue("_NextExtension", _NextExtension); 

    } 
    public FakeHttpWebRequest() 
     : base(SerializationInfo, new StreamingContext()) 
    { 
     _requestStream = new MemoryStream(); 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="T:System.Net.HttpWebRequest"/> class from the specified instances of the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> and <see cref="T:System.Runtime.Serialization.StreamingContext"/> classes. 
    /// </summary> 
    /// <param name="serializationInfo">A <see cref="T:System.Runtime.Serialization.SerializationInfo"/> object that contains the information required to serialize the new <see cref="T:System.Net.HttpWebRequest"/> object. </param><param name="streamingContext">A <see cref="T:System.Runtime.Serialization.StreamingContext"/> object that contains the source and destination of the serialized stream associated with the new <see cref="T:System.Net.HttpWebRequest"/> object. </param> 
    protected FakeHttpWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) 
     : base(serializationInfo, streamingContext) 
    { 
    } 

    #region Overrides of HttpWebRequest 

    /// <summary> 
    /// Gets a <see cref="T:System.IO.Stream"/> object to use to write request data. 
    /// </summary> 
    /// <returns> 
    /// A <see cref="T:System.IO.Stream"/> to use to write request data. 
    /// </returns> 
    /// <exception cref="T:System.Net.ProtocolViolationException">The <see cref="P:System.Net.HttpWebRequest.Method"/> property is GET or HEAD.-or- <see cref="P:System.Net.HttpWebRequest.KeepAlive"/> is true, <see cref="P:System.Net.HttpWebRequest.AllowWriteStreamBuffering"/> is false, <see cref="P:System.Net.HttpWebRequest.ContentLength"/> is -1, <see cref="P:System.Net.HttpWebRequest.SendChunked"/> is false, and <see cref="P:System.Net.HttpWebRequest.Method"/> is POST or PUT. </exception><exception cref="T:System.InvalidOperationException">The <see cref="M:System.Net.HttpWebRequest.GetRequestStream"/> method is called more than once.-or- <see cref="P:System.Net.HttpWebRequest.TransferEncoding"/> is set to a value and <see cref="P:System.Net.HttpWebRequest.SendChunked"/> is false. </exception><exception cref="T:System.NotSupportedException">The request cache validator indicated that the response for this request can be served from the cache; however, requests that write data must not use the cache. This exception can occur if you are using a custom cache validator that is incorrectly implemented. </exception><exception cref="T:System.Net.WebException"><see cref="M:System.Net.HttpWebRequest.Abort"/> was previously called.-or- The time-out period for the request expired.-or- An error occurred while processing the request. </exception><exception cref="T:System.ObjectDisposedException">In a .NET Compact Framework application, a request stream with zero content length was not obtained and closed correctly. For more information about handling zero content length requests, see Network Programming in the .NET Compact Framework.</exception><PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Net.DnsPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Net.WebPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet> 
    public override Stream GetRequestStream() 
    { 
     return _requestStream; 
    } 

    #endregion 
}