문제

내가 마지막으로 시작으로 장난을 만드는 일부 응용 프로그램을 작품으로 편안한 웹 인터페이스,그러나 나는 우려가 나는 망치로 치는 자신의 서버에 알 F5 을 실행하는 일련의 테스트를..

기본적으로,필요 시리즈의 웹 응답을 테스트 할 수 있도록 저는 구문 분석하는 다양한 응답에 올바르게,보다는 오히려 자신의 서버에 모든 시간,나는 생각에 나는 이렇게 할 수 있다면,저장 XML 다음 작업합니다.

그러나 나는 보이지 않는 어떻게 할 수 있습니다"모"a WebResponse,이후(AFAIK)그들은 단지 인스턴스화에 의해 WebRequest.GetResponse

너희들은 어떻게 이동에 대한 조롱의 이런 종류의 것은?니까?나는 그냥 정말 좋아하지 않는 사실 나는 망의 서버가:S 싶을 변경하는 코드 지만,나는 기대가있는 우아한 방법으로 일을 이해합니다.

업데이트 다음과 같은 허용

이의 대답이었을 때리고 얼굴을 내가 필요하고,내가 누락되었 근본적인 관점!

  • 는 인터페이스를 만들이 반환됩니다 프록시는 개체를 나타내는 XML.
  • 인터페이스를 구현하고,두 번 중 하나를 사용하는 WebRequest,다른 반환하는 정적"응답".
  • 인터페이스 implmentation 다음 중 하나 인스턴스화익 유형 응답에 기초하여,또는 정적 XML.
  • 전달할 수 있습니다 필요한 클래스를 테스트할 때 또는에서 생산하는 서비스 계층입니다.

면 나는 코드를 두,나를 붙여 넣습니다.

도움이 되었습니까?

해결책

내가 찾은 이 질문에 보면을 정확하게 하기 위하여 동일한 것입니다.답을 찾을 수가 없었어나지만,조금 더 파고 후는 것을 발견.Net 프레임워크는 지원 내장합니다.

당신이 등록할 수 있는 공장체 WebRequest.RegisterPrefixWebRequest.Create 를 호출할 때 사용하는 접두사(url).공장을 구현해야 합니다 IWebRequestCreate 는 하나의 방법 Create 을 반환하는 WebRequest.여기에 반환할 수 있습니다 당신의 목 WebRequest.

나는 몇 가지 예제 코드에서 http://blog.salamandersoft.co.uk/index.php/2009/10/how-to-mock-httpwebrequest-when-unit-testing/

다른 팁

여기에는 솔루션이 필요하지 않 조롱.를 구현하는 세 가지 모든 구성 요소의 WebRequest: IWebRequestCreate WebRequestWebResponse.아래를 참조하십시오.내 예를 생성한 실패 요청(던지 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() method)을 먹이의 값을 무시할 수는 없습니다,예를 들어, StatusCode 이것이 우리의 절친한 친구 SerializaionInfo 다.이것은 당신을 공급한 값을 무시할 수는 없습니다.물론,재정의 부분(의 HttpWebResponse 다)당신은 수를 얻을,나머지 방법이 있다.

나는 어떻게 얻을 수"이름"에서 모든 사람들 AddValue() 니다.에서 예외를 제공하지 않습니다.그것은 좋은 충분히 말해 모든 차례로 만들 때까지 그것이 행복입니다.

이제,컴파일러는 불평에 대한"사용되지 않"이지만 그럼에도 불구하고 작동합니다.NET 프레임워크 버전 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;
        }
    }

당신은 할 수 없습니다.할 수있는 가장 좋은 방법은 포장에 프록시가 객체를 모니다.또는,당신은 당신을 사용하여 조롱하는 프레임워크를 차단할 수 있 유형할 수 없는 조롱하며,다음과 같 TypeMock.하지만 당신은 이야기에 대한 달러 수 있습니다.더 작은 포장됩니다.


분명히 당신 약간의 추가와 함께 작동합니다.체크인 가장 높은 투표니다.

내가 찾은 다음과 같은 블로그에 앞서 설명하는 아주 좋은 방법을 사용하여 Microsoft 몰.

http://maraboustork.co.uk/index.php/2011/03/mocking-httpwebresponse-with-moles/

에서 짧은 솔루션을 제안 다음과 같다:

    [TestMethod]
    [HostType("Moles")]
    [Description("Tests that the default scraper returns the correct result")]
    public void Scrape_KnownUrl_ReturnsExpectedValue()
    {
        var mockedWebResponse = new MHttpWebResponse();

        MHttpWebRequest.AllInstances.GetResponse = (x) =>
        {
            return mockedWebResponse;
        };

        mockedWebResponse.StatusCodeGet = () => { return HttpStatusCode.OK; };
        mockedWebResponse.ResponseUriGet = () => { return new Uri("http://www.google.co.uk/someRedirect.aspx"); };
        mockedWebResponse.ContentTypeGet = () => { return "testHttpResponse"; }; 

        var mockedResponse = "<html> \r\n" +
                             "  <head></head> \r\n" +
                             "  <body> \r\n" +
                             "     <h1>Hello World</h1> \r\n" +
                             "  </body> \r\n" +
                             "</html>";

        var s = new MemoryStream();
        var sw = new StreamWriter(s);

            sw.Write(mockedResponse);
            sw.Flush();

            s.Seek(0, SeekOrigin.Begin);

        mockedWebResponse.GetResponseStream = () => s;

        var scraper = new DefaultScraper();
        var retVal = scraper.Scrape("http://www.google.co.uk");

        Assert.AreEqual(mockedResponse, retVal.Content, "Should have returned the test html response");
        Assert.AreEqual("http://www.google.co.uk/someRedirect.aspx", retVal.FinalUrl, "The finalUrl does not correctly represent the redirection that took place.");
    }

이것은 완벽한 솔루션이 아직 그것이 나를 위해 일하기 전에 그 가치가분의 관리를 단순:

HTTPSimulator

또한 typemock 예제에서 설명 typemock 포럼:

using System;
using System.IO;
using System.Net;
using NUnit.Framework;
using TypeMock;

namespace MockHttpWebRequest
{
  public class LibraryClass
  {
    public string GetGoogleHomePage()
    {
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
      HttpWebResponse response = (HttpWebResponse)request.GetResponse();
      using (StreamReader reader = new StreamReader(response.GetResponseStream()))
      {
        return reader.ReadToEnd();
      }
    }
  }

  [TestFixture]
  [VerifyMocks]
  public class UnitTests
  {
    private Stream responseStream = null;
    private const string ExpectedResponseContent = "Content from mocked response.";

    [SetUp]
    public void SetUp()
    {
      System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
      byte[] contentAsBytes = encoding.GetBytes(ExpectedResponseContent);
      this.responseStream = new MemoryStream();
      this.responseStream.Write(contentAsBytes, 0, contentAsBytes.Length);
      this.responseStream.Position = 0;
    }

    [TearDown]
    public void TearDown()
    {
      if (responseStream != null)
      {
        responseStream.Dispose();
        responseStream = null;
      }
    }

    [Test(Description = "Mocks a web request using natural mocks.")]
    public void NaturalMocks()
    {
      HttpWebRequest mockRequest = RecorderManager.CreateMockedObject<HttpWebRequest>(Constructor.Mocked);
      HttpWebResponse mockResponse = RecorderManager.CreateMockedObject<HttpWebResponse>(Constructor.Mocked);
      using (RecordExpectations recorder = RecorderManager.StartRecording())
      {
        WebRequest.Create("http://www.google.com");
        recorder.CheckArguments();
        recorder.Return(mockRequest);

        mockRequest.GetResponse();
        recorder.Return(mockResponse);

        mockResponse.GetResponseStream();
        recorder.Return(this.responseStream);
      }

      LibraryClass testObject = new LibraryClass();
      string result = testObject.GetGoogleHomePage();
      Assert.AreEqual(ExpectedResponseContent, result);
    }

    [Test(Description = "Mocks a web request using reflective mocks.")]
    public void ReflectiveMocks()
    {
      Mock<HttpWebRequest> mockRequest = MockManager.Mock<HttpWebRequest>(Constructor.Mocked);
      MockObject<HttpWebResponse> mockResponse = MockManager.MockObject<HttpWebResponse>(Constructor.Mocked);
      mockResponse.ExpectAndReturn("GetResponseStream", this.responseStream);
      mockRequest.ExpectAndReturn("GetResponse", mockResponse.Object);

      LibraryClass testObject = new LibraryClass();
      string result = testObject.GetGoogleHomePage();
      Assert.AreEqual(ExpectedResponseContent, result);
    }
  }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top