3

I wanted to try Moq to mock a request object for simulating things like network failure on in my test cases. My first attempt was:

        var mock = new Mock<WebRequest>();
        mock.Setup(m => m.GetResponse()).Throws<WebException>();
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        //trying to get this to throw a web exception
        request.GetResponse();

This is not working so I'm looking for the correct way to do this.

Thanks

EDIT: as pointed out in the comments I'd like to use WebRequest.Create (it's actually in another method but I've simplified for the example).

4
  • 1
    Your sample seem strange - you setup one object but hope to get exception on totally different one. What is wrong with mock.Object.GetResponse()? Or you are trying to actually intercept execution of WebRequst.Create static factory method? Commented Mar 4, 2013 at 2:16
  • @AlexeiLevenkov is absolutely right, I'd suggest it will be an answer as it is the correct one. Commented Mar 4, 2013 at 2:17
  • @OferZelig, while it may be ok, I strongly doubt directedbit wants that - I suspect the code under test actually uses Create instead of taking dependency on passed in request object (or custom mockable factory) - so unlikely to be helpful. Waiting for OP to comment. Commented Mar 4, 2013 at 2:19
  • @Alexi the code is actually called in another method (i simplified it) so I guess it means I'll have to pass it in as an argument. In other languages I've used (e.g ruby) you can redefine the method call so new instances would call the stub and I'd assumed that behaviour. Commented Mar 4, 2013 at 2:21

1 Answer 1

9

Static methods and factories (like WebRequest.Create) are pain for unit testing. Some such factory methods allow intercepting/customizing results, some not.

The most straightforward solution is to have own factory method (preferably in form of an interface) that your code will depend on.

In some cases you can pass already created object to your code under test instead of letting code to create own.

In particular case of WebRequest.Create you may be able to provide your own factory via WebRequest.RegisterPrefix. Looking at description you will need to use some other custom Uri scheme as "http"/"https" are already registerd and duplicate registration is not allowed (also I never tried this approach).

Here is a sample code that provides custom creator for "http://" scheme in console application. This code probably will fail in case something else already registers http scheme with WebRequest:

using System;
using System.Net;
namespace CustomWebRequest
{
    class Program
    {
        static void Main(string[] args)
        {
            var success = WebRequest.RegisterPrefix("http://", new CustomRequestCreator());
            Console.Write("Handler registered:{0}", success);

            var request = WebRequest.Create(new Uri("http://home.com"));
        }

        class CustomRequestCreator : IWebRequestCreate
        {
            public WebRequest Create(Uri uri)
            {
                Console.WriteLine("Custom creator");
                return null; // return your mock here...
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.