これは、モックを必要としないソリューションです。WebRequest
:IWebRequestCreate
WebRequest
との 3 つのコンポーネントすべてを実装しますWebResponse
。下記参照。私の例では、( をスローすることによって) 失敗したリクエストが生成されWebException
ますが、「実際の」応答を送信するように適応できるはずです。
class WebRequestFailedCreate : IWebRequestCreate {
HttpStatusCode status;
String statusDescription;
public WebRequestFailedCreate(HttpStatusCode hsc, String sd) {
status = hsc;
statusDescription = sd;
}
#region IWebRequestCreate Members
public WebRequest Create(Uri uri) {
return new WebRequestFailed(uri, status, statusDescription);
}
#endregion
}
class WebRequestFailed : WebRequest {
HttpStatusCode status;
String statusDescription;
Uri itemUri;
public WebRequestFailed(Uri uri, HttpStatusCode status, String statusDescription) {
this.itemUri = uri;
this.status = status;
this.statusDescription = statusDescription;
}
WebException GetException() {
SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new System.Runtime.Serialization.FormatterConverter());
StreamingContext sc = new StreamingContext();
WebHeaderCollection headers = new WebHeaderCollection();
si.AddValue("m_HttpResponseHeaders", headers);
si.AddValue("m_Uri", itemUri);
si.AddValue("m_Certificate", null);
si.AddValue("m_Version", HttpVersion.Version11);
si.AddValue("m_StatusCode", status);
si.AddValue("m_ContentLength", 0);
si.AddValue("m_Verb", "GET");
si.AddValue("m_StatusDescription", statusDescription);
si.AddValue("m_MediaType", null);
WebResponseFailed wr = new WebResponseFailed(si, sc);
Exception inner = new Exception(statusDescription);
return new WebException("This request failed", inner, WebExceptionStatus.ProtocolError, wr);
}
public override WebResponse GetResponse() {
throw GetException();
}
public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) {
Task<WebResponse> f = Task<WebResponse>.Factory.StartNew (
_ =>
{
throw GetException();
},
state
);
if (callback != null) f.ContinueWith((res) => callback(f));
return f;
}
public override WebResponse EndGetResponse(IAsyncResult asyncResult) {
return ((Task<WebResponse>)asyncResult).Result;
}
}
class WebResponseFailed : HttpWebResponse {
public WebResponseFailed(SerializationInfo serializationInfo, StreamingContext streamingContext)
: base(serializationInfo, streamingContext) {
}
}
HttpWebResponse
サブクラスを作成しないと作成できないため、サブクラスを作成する必要があります。
(メソッド内で) トリッキーな部分は、GetException()
オーバーライドできない値を入力することです。たとえばStatusCode
、これが私たちの最高の相棒のSerializaionInfo
出番です! ここで、オーバーライドできない値を指定します。明らかに、(のHttpWebResponse
) 可能な部分をオーバーライドして、残りの部分を取得します。
これらすべてのAddValue()
呼び出しで「名前」を取得するにはどうすればよいですか? 例外メッセージから!幸せになるまで、一人一人順番に教えてくれて良かったです。
現在、コンパイラは「廃止」について不平を言うでしょうが、それでも.NET Framework バージョン 4 を含めてこれは機能します。
参照用の(合格)テストケースは次のとおりです。
[TestMethod, ExpectedException(typeof(WebException))]
public void WebRequestFailedThrowsWebException() {
string TestURIProtocol = TestContext.TestName;
var ResourcesBaseURL = TestURIProtocol + "://resources/";
var ContainerBaseURL = ResourcesBaseURL + "container" + "/";
WebRequest.RegisterPrefix(TestURIProtocol, new WebRequestFailedCreate(HttpStatusCode.InternalServerError, "This request failed on purpose."));
WebRequest wr = WebRequest.Create(ContainerBaseURL);
try {
WebResponse wrsp = wr.GetResponse();
using (wrsp) {
Assert.Fail("WebRequest.GetResponse() Should not have succeeded.");
}
}
catch (WebException we) {
Assert.IsInstanceOfType(we.Response, typeof(HttpWebResponse));
Assert.AreEqual(HttpStatusCode.InternalServerError, (we.Response as HttpWebResponse).StatusCode, "Status Code failed");
throw we;
}
}