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.