moq HttpWebRequest对象

pro*_*ach 3 c# moq mocking

我想尝试Moq来模拟一个请求对象,以便在我的测试用例中模拟网络故障.我的第一次尝试是:

        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();
Run Code Online (Sandbox Code Playgroud)

这不起作用,所以我正在寻找正确的方法来做到这一点.

谢谢

编辑:正如评论中所指出的,我想使用WebRequest.Create(它实际上是另一种方法,但我已经简化了示例).

Ale*_*kov 8

静态方法和工厂(如WebRequest.Create)是单元测试的痛苦.一些这样的工厂方法允许拦截/定制结果,一些不允许.

最直接的解决方案是拥有您的代码所依赖的自己的工厂方法(最好以接口的形式).

在某些情况下,您可以将已创建的对象传递给测试中的代码,而不是让代码创建自己的代码.

在特殊情况下,WebRequest.Create您可以通过WebRequest.RegisterPrefix提供自己的工厂.查看描述,您将需要使用其他一些自定义Uri方案,因为"http"/"https"已经注册并且不允许重复注册(我也从未尝试过这种方法).

下面是一个示例代码,它为控制台应用程序中的"http://"方案提供自定义创建者.如果其他东西已经注册了http scheme,则此代码可能会失败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...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)