2015-01-30 5 views
1

У меня есть этот класс:Как протестировать HttpWebRequest Зависимый метод?

public class RestClient 
{ 
    public RestClient() 
    { } 

    protected virtual HttpWebRequest CreateHttpWebRequest(Uri uri) 
    { 
     return (HttpWebRequest)HttpWebRequest.Create(uri); 
    } 


    /// <summary> 
    /// Perform a http POST request in order to push data to server 
    /// </summary> 
    /// <param name="uri">End Point Uri</param> 
    /// <param name="data">Data to be transmitted</param> 
    /// <returns></returns> 
    /// 
    public long PostRequest(Uri uri,string data) 
    { 

     try 
     { 
      HttpWebRequest request = CreateHttpWebRequest(uri); //(HttpWebRequest)HttpWebRequest.Create(uri); 

      request.Method = "POST"; 
      request.ContentType = "application/json"; 

      System.Text.UTF8Encoding encoding = new UTF8Encoding(); 

      byte[] bytes = encoding.GetBytes(data); 



      using (Stream requestStream = request.GetRequestStream()) 
      { 
       //Transmit data 
       requestStream.Write(bytes, 0, bytes.Length); 
       requestStream.Flush(); 
       requestStream.Close(); 
      } 



      //Get the Response from the server 
      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
      { 
       if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.NoContent) 
       { 
        throw new Exception(String.Format(
         "Server error (HTTP {0}: {1}).", 
          response.StatusCode, 
           response.StatusDescription)); 
       } 
      } 


      return request.ContentLength; 
     } 
     catch (Exception e) 
     { 
      throw e; 
     } 

    }  

} 

И хотел бы Unit тест (с использованием NUnit) PostRequest метод.

Проведя некоторые исследования, я мог бы найти способ издеваться над HttpWebRequest в этом посте (Is it possible to mock out a .NET HttpWebResponse?) и способ ввести его в класс в этом сообщении (How to unit test a method with HttpWebRequest/Response dependencies).

Однако, когда я пытался проверить мой метод, который я получил эту ошибку:

System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.IHttpWebRequestProxy' to type 'System.Net.HttpWebRequest'. 

в этой линии моего теста

client.HttpWebRequestFake = (HttpWebRequest)factory.Object.Create("http://127.0.0.1"); 

Это мой тестовый код:

public class TesableRestClient : RestClient 
{ 
    public HttpWebRequest HttpWebRequestFake { get; set; } 

    protected override HttpWebRequest CreateHttpWebRequest(Uri url) 
    { 
     if (HttpWebRequestFake != null) 
      return HttpWebRequestFake; 
     return base.CreateHttpWebRequest(url); 
    } 
} 


[TestFixture] 
public class TransferWebRequestTest 
{ 
    [Test] 
    public void TestPostResquest() 
    { 
     string expectedContent = "Content"; 
     var expectedBytes = Encoding.UTF8.GetBytes(expectedContent); 
     var responseStream = new MemoryStream(); 
     responseStream.Write(expectedBytes, 0, expectedBytes.Length); 
     responseStream.Seek(0, SeekOrigin.Begin); 

     var response = new Mock<IHttpWebResponse>(); 
     response.Setup(c => c.GetResponseStream()).Returns(responseStream); 

     var request = new Mock<IHttpWebRequest>(); 
     request.Setup(c => c.GetResponse()).Returns(response.Object); 

     var factory = new Mock<IHttpWebRequestFactory>(); 
     factory.Setup(c => c.Create(It.IsAny<string>())) 
      .Returns(request.Object); 

     TesableRestClient client = new TesableRestClient(); 
     client.HttpWebRequestFake = (HttpWebRequest)factory.Object.Create("http://127.0.0.1"); 

     // DoStuff call the url with a request and then processes the 
     long bytesSent = client.PostRequest(new Uri("http://127.0.0.1"), expectedContent); 
     Assert.AreEqual(expectedBytes, bytesSent); 
} 

HttpWebRequest/Response:

public interface IHttpWebRequest 
{ 
    // expose the members you need 
    string Method { get; set; } 
    string ContentType { get; set; } 
    long ContentLength { get; set; } 
    IHttpWebResponse GetResponse(); 
} 

public interface IHttpWebResponse : IDisposable 
{ 
    // expose the members you need 
    HttpStatusCode StatusCode { get; } 
    string StatusDescription { get;} 
    Stream GetResponseStream(); 
} 

public interface IHttpWebRequestFactory 
{ 
    IHttpWebRequest Create(string uri); 
} 

// barebones implementation 

public class HttpWebRequestFactory : IHttpWebRequestFactory 
{ 
    public IHttpWebRequest Create(string uri) 
    { 
     return new WrapHttpWebRequest((HttpWebRequest)WebRequest.Create(uri)); 
    } 
} 

public class WrapHttpWebRequest : IHttpWebRequest 
{ 
    private readonly HttpWebRequest _request; 

    public WrapHttpWebRequest(HttpWebRequest request) 
    { 
     _request = request; 
    } 

    public string Method 
    { 
     get { return _request.Method; } 
     set { _request.Method = value; } 
    } 

    public string ContentType 
    { 
     get { return _request.ContentType; } 
     set { _request.ContentType = value; } 
    } 

    public long ContentLength 
    { 
     get { return _request.ContentLength; } 
     set { _request.ContentLength = value; } 
    } 

    public IHttpWebResponse GetResponse() 
    { 
     return new WrapHttpWebResponse((HttpWebResponse)_request.GetResponse()); 
    } 
} 

public class WrapHttpWebResponse : IHttpWebResponse 
{ 
    private HttpWebResponse _response; 

    public WrapHttpWebResponse(HttpWebResponse response) 
    { 
     _response = response; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (_response != null) 
      { 
       ((IDisposable)_response).Dispose(); 
       _response = null; 
      } 
     } 
    } 

    public Stream GetResponseStream() 
    { 
     return _response.GetResponseStream(); 
    } 

    public HttpStatusCode StatusCode 
    { 
     get { return _response.StatusCode; } 
    } 

    public string StatusDescription 
    { 
     get { return _response.StatusDescription; } 
    } 

} 

Любая идея, как я мог это решить?

Спасибо

+0

Прочитайте сообщение об ошибке, он говорит вам проблему. Если вы проверите свой код, класс 'WrapHttpWebRequest' не имеет типа' HttpWebRequest'. –

ответ

0

Не совсем уверен, что вы хотите достичь, но это может помочь. Сообщение об ошибке сообщает вам точную проблему и дает вам подсказку, что делать.

Если вы проверили ваш код, класс WrapHttpWebRequest не относится к типу HttpWebRequest. Однако он содержит HttpWebRequest. Эти два шага решают прямую проблему, но вы можете столкнуться с другой проблемой. Во-первых, обеспечить свойство класса WrapHttpWebRequest:

public HttpWebRequest HttpWebRequest { get { return _request; } } 

Затем изменить вы неудачу строку кода для этого:

client.HttpWebRequestFake = factory.Object.Create("http://127.0.0.1").HttpWebRequest; 

Я считаю, однако, что было бы лучше, чтобы изменить класс WrapHttpWebRequest и наследовать от ' HttpWebRequest ', как это ...

public class WrapHttpWebRequest: HttpWebRequest, IHttpWebRequest 

... и соответствующим образом изменить его реализацию.

+0

Я пытаюсь проверить свой метод без запуска сервера Http. У меня есть googled, но couold не нашел что-то, что сработало бы для меня, кроме двух ссылок, которые я опубликовал –

1

я решил мою проблему делает последующие:

Во-первых, создал интерфейс IHttpWebRequestFactory

public interface IHttpWebRequestFactory 
{ 
    HttpWebRequest Create(string uri); 
} 

В классе, который я хочу проверить, я создал следующие методы:

protected virtual HttpWebRequest CreateHttpWebRequest(Uri uri) 
    { 
     return (HttpWebRequest)HttpWebRequest.Create(uri); 
    } 

    protected virtual HttpWebResponse GetHttpWebResponse(HttpWebRequest request) 
    { 
     return (HttpWebResponse)request.GetResponse(); 
    } 

В моем тестовом файле я создал класс «Testable», который наследует класс, который я действительно хочу проверить и переопределяет виртуальные методы:

//Class Created to test the PostRequestMethod 
public class TestableRestClient : RestClient 
{ 
    public HttpWebRequest HttpWebRequestFake { get; set; } 

    public string responseValue; 

    protected override HttpWebRequest CreateHttpWebRequest(Uri url) 
    { 
     if (HttpWebRequestFake != null) 
      return HttpWebRequestFake; 
     return base.CreateHttpWebRequest(url); 
    } 

    protected override HttpWebResponse GetHttpWebResponse(HttpWebRequest request) 
    { 
     HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
     using (var streamReader = new StreamReader(request.GetResponse().GetResponseStream())) 
     { 
      responseValue = streamReader.ReadToEnd(); 
     } 
     return base.GetHttpWebResponse(request); 
    } 
} 

Тогда я использовал Moq для имитации поведения методов, которые я использую в своем классе

[TestFixture] 
public class DMSTransferWebRequestTest 
{ 
    [Test] 
    public void TestPostResquest() 
    {  

     string expected = "Content"; 

     //Prepare the Mocked Response Stream 
     byte [] expectedBytes = Encoding.UTF8.GetBytes(expected); 
     Stream responseStream = new MemoryStream(); 
     responseStream.Write(expectedBytes, 0, expectedBytes.Length); 
     responseStream.Seek(0, SeekOrigin.Begin); 

     //Prepare the Mocked Request Stream 
     Stream requestStream = new MemoryStream(); 
     requestStream.Write(expectedBytes, 0, expectedBytes.Length); 
     requestStream.Seek(0, SeekOrigin.Begin); 

     //Mock the HttpWebResponse 
     Mock<HttpWebResponse> response = new Mock<HttpWebResponse>(); 

     //Set the method GetResponseStream to return the Response Stream mocked 
     response.Setup(c => c.GetResponseStream()).Returns(responseStream); 
     response.Setup(c => c.StatusCode).Returns(HttpStatusCode.OK); 

     //Set the method GetRequestStream to return the Request Stream mocked 
     Mock<HttpWebRequest> request = new Mock<HttpWebRequest>(); 
     request.Setup(c => c.GetResponse()).Returns(response.Object); 
     request.Setup(c => c.GetRequestStream()).Returns(requestStream); 

     //Create a Object to mock the HttpWebRequest Create Method 
     Mock<IHttpWebRequestFactory> factory = new Mock<IHttpWebRequestFactory>(); 
     factory.Setup(c => c.Create(It.IsAny<string>())) 
      .Returns(request.Object); 


     TestableRestClient client = new TestableRestClient(); 
     client.HttpWebRequestFake = factory.Object.Create("http://mytest"); 

     long actualBytes = client.PostRequest(new Uri("http://mytest"), expected); 

     string actual = client.responseValue; 


     Assert.AreEqual(expected, actual); 

    } 
} 
Смежные вопросы