chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Just started using TypeMock. Looks promising, but it seems like we have run into a rather tricky issue. We are trying to test this piece of code:

public string DoPostRequest(string url, string data, int timeout)
{
            HttpWebRequest objRequest = WebRequest.Create(url) as HttpWebRequest;
            objRequest.Timeout = timeout;
            objRequest.Method = "POST";
            objRequest.ContentLength = data.Length;

            using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
            {
                myWriter.Write(data);
            }

            HttpWebResponse objResponse = objRequest.GetResponse() as HttpWebResponse;

            string result;
            using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
            {
                result = sr.ReadToEnd();
            }
            return result;
}


This turns out to be *incredibly* tricky, since neither HttpWebRequest or HttpWebResponse has public constructors. Nor do they have interfaces. Thanks for that, Microsoft. :P

We can get half-way by actually creating a real HttpWebRequest object with WebRequest.Create(url) and then just mocking the method calls on it, but after that, we need HttpWebRequest.GetResponse() to return an actual Response (since we cannot mock it) and we cannot, for the life of us, figure out how to create such an object.

Here's some code to illustrate the issue:
        [Test]
        public void TypeMockingHttpWebResponseTestTest()
        {
            Stream stream = new MemoryStream();

            //This is our problem, there is no way to instanciate HttpWebResponse independant of a request.
            HttpWebResponse webResponseInstance = new HttpWebResponse(); //<-That doesn't work

            using (RecordExpectations recorder = RecorderManager.StartRecording())
            {
                WebRequest.Create("http://sampleurl.com");
                recorder.CallOriginal().CheckArguments();

                Mock webRequestMock = MockManager.MockAll(typeof(HttpWebRequest));
                webRequestMock.ExpectAndReturn("GetResponse", webResponseInstance);

                Mock webResponseMock = MockManager.MockAll(typeof(HttpWebResponse));
                webResponseMock.ExpectAndReturn("GetResponseStream", stream);
            }

            WebRequest webRequest = WebRequest.Create("http://sampleurl.com");
            HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
            Assert.IsNotNull(webResponse);
            Stream retrievedResponseStream = webResponse.GetResponseStream();
            Assert.AreEqual(stream, retrievedResponseStream);

        }



We found this old thread( over 2 years old)...
https://www.typemock.com/community/viewt ... ebresponse
... where scott suggests multiple solutions to the problem with code snippets, of which none unfortunately works in practice. I have not tried his last solution (Post subject: Try using the Enterise Edition) as we did not quite understand how it applied to the problem at hand. If anyone could explain it's usage more detailed, that would be great.

Also, one of the more interesting approaches he suggested was to create a HttpWebRequest this way:

// mock next WebRequest
    Mock httpWebRequestMock = MockManager.Mock(typeof(HttpWebRequest));

    // mock next WebResponse
    Mock httpWebResponseMockControl = MockManager.Mock(typeof(HttpWebResponse));
    // args for WebResponse
    object[] args = new object[] { new SerializationInfo(typeof(string),
      new FormatterConverter()),
      new StreamingContext(StreamingContextStates.All)};

    // create the WebResponse
    HttpWebResponse mockHttpWebResponse =
       Activator.CreateInstance(typeof(HttpWebResponse),
       BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
       null,args,null) as HttpWebResponse;

    // set Request to return our mockResponse        
    httpWebRequestMock.ExpectAndReturn("GetResponse",
       mockHttpWebResponse); 


However, that ejaculates this wonderful error:

System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> System.Runtime.Serialization.SerializationException : Member 'm_HttpResponseHeaders' was not found.
   at System.RuntimeMethodHandle._InvokeConstructor(Object[] args, SignatureStruct& signature, IntPtr declaringType)
   at System.RuntimeMethodHandle.InvokeConstructor(Object[] args, SignatureStruct signature, RuntimeTypeHandle declaringType)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)



Can anyone shed light on this issue? Mocking HttpRequest seems to be the holy grail of mocking.
asked by M. Johansson (2.2k points)

2 Answers

0 votes
Hi,

I understand from your other post "Natural TypeMock equivalent of MockObject.Object?"
onhttps://www.typemock.com/community/viewtopic.php?p=2751#2751
that you have figured out the API for reflective. Does this answer your question?
answered by gilz (14.5k points)
0 votes
Here's an example of mocking an HttpWebRequest/HttpWebResponse using both Natural and Reflective mocks.

  • I simplified the scenario here for illustration. You could expand it to be your parameterized example, too.
  • In my unit tests I have some common setup and teardown for the expected response stream and contents. From a purist standpoint, you'd probably want this in each test, but it makes the example really long.
  • The reflective mock example is shorter in lines of code than the natural mock example, but the natural mock example has the benefits of readability, compile-time checking, and specific response to the WebRequest.Create() call, where the reflective mocks don't. I'd recommend going with the natural mocks if you can.
  • I'm using the VerifyMocks attribute to handle the verify/clear of mocks. It keeps the tests nice and clean and really enhances the view in the trace utility by showing me exactly which tests are setting up which expectations.

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);
    }
  }
}
answered by tillig (6.7k points)
...