Unit testing 如何对依赖于HttpWebRequest和HttpWebResponse的现有代码进行单元测试?

Unit testing 如何对依赖于HttpWebRequest和HttpWebResponse的现有代码进行单元测试?,unit-testing,visual-studio-2012,serialization,.net-4.5,webrequest,Unit Testing,Visual Studio 2012,Serialization,.net 4.5,Webrequest,我已经看到了以下问题: “” “” 这些对我没有帮助,因为我需要: 测试直接使用WebRequest/WebResponse且无接口的现有代码 现有代码依赖于HttpWebRequest/HttpWebResponse,因此我不能使用自己派生的WebRequest和WebResponse类 我了解WebRequest.RegisterPrefix,并进行了成功的单元测试,证明它是有效的(只要前缀正确)。但该测试只是测试WebRequest和WebResponse 我尝试了以下操作,但它给出了

我已经看到了以下问题:

  • “”
  • “”
这些对我没有帮助,因为我需要:

  • 测试直接使用
    WebRequest
    /
    WebResponse
    且无接口的现有代码
  • 现有代码依赖于
    HttpWebRequest
    /
    HttpWebResponse
    ,因此我不能使用自己派生的
    WebRequest
    WebResponse
  • 我了解
    WebRequest.RegisterPrefix
    ,并进行了成功的单元测试,证明它是有效的(只要前缀正确)。但该测试只是测试
    WebRequest
    WebResponse

    我尝试了以下操作,但它给出了一个编译错误(不是警告):

    注释掉两行后,我得到一个编译错误:

    错误CS0619:“System.Net.HttpWebRequest.HttpWebRequest()”已过时:“此API支持.Net Framework基础结构,不打算直接从代码中使用。”

    当我取消注释这些行时,会收到618警告,但代码在运行时崩溃:

    System.Runtime.Serialization.SerializationException: Member '_HttpRequestHeaders' was not found.
       at System.Runtime.Serialization.SerializationInfo.GetElement(String name, Type& foundType)
       at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
       at System.Net.HttpWebRequest..ctor(SerializationInfo serializationInfo, StreamingContext streamingContext)
       at UnitTests.MockWebRequest..ctor(String responseJson)
       at UnitTests.MockWebRequestCreator.Create(Uri uri)
       at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
       at System.Net.WebRequest.Create(Uri requestUri)
       at code under test
    
    我不知道如何继续进行这项工作(除了默认情况,默认情况是只在这些单元测试上下赌注,并希望代码是在考虑测试的情况下实现的)

    我可能会“下不了台”,用
    ISerializable
    ,或诸如此类的东西做一些讨厌的事情,但这带来了第三个要求:

    3.
    代码必须是可维护的,并且不能比正在测试的代码复杂太多


    哎呀,我不能用TypeMock来做这个,事实上还有一点时间限制。该项目即将完成,因此购买新的模拟框架是不可能的。

    在模拟诸如httpcontext之类的asp.net单例时,我通常更喜欢使用MOQ之类的模拟框架

    还有其他的模拟框架,但我发现MOQ非常灵活和直观

    你可以做类似的事情

    另一种方法是通过虚拟方法抽象对httpcontext的调用: 与此技术类似:
    我刚刚遇到了同样的问题。坦率地说,微软的设置方式没有多大意义——在WebRequest中。他们有一个抽象工厂,但他们既没有为我们可以实现的HttpWebRequest和HttpWebResponse提供接口,也没有提供我们可以用来从这些类继承的受保护构造函数

    我提出的解决方案需要对主程序进行一些小的更改,但它是有效的。基本上,我正在做微软应该做的事情

  • 创建接口IHttpWebRequest和IHttpWebResponse
  • 创建实现接口的模拟类
  • 为实现接口的HttpWebRequest和HttpWebResponse创建包装器
  • 替换对WebRequest.Create的调用,并根据需要使用我自己的工厂方法返回包装器或模拟
  • 根据您的代码是如何构造的,上述内容可能实现起来比较简单,或者可能需要在整个项目中进行更改。在我的例子中,我们所有的HTTP请求都通过一个公共服务,所以还不算太糟糕


    无论如何,对于您的项目来说可能太晚了,但这可能会帮助其他人。

    不幸的是,对于
    HttpWebRequest
    ,没有与
    HttpContextBase
    等价的东西。没有
    HttpWebRequestBase
    class.Ok。我添加了另一种我有时使用的方法,我担心这也不会有帮助。正如我在问题中所说的,我不能对测试中的代码进行更改。。我想另一个想法可能是做一个完整的集成测试,在这里,您可以使用一个常规的https请求来访问您的端点(控制器等)。可以从测试中的命令行启动IIS express。这可能并不理想,但至少可以让您断言由测试代码引起的更改。然而,这并不是一个传统的单元测试思想,我有一个疯狂的想法,就是将任务委托给真正的
    HttpWebRequest
    HttpWebResponse
    。我将继续注册我的
    test://localhost/
    prefix,但注册的处理程序将委托给实际类,但会遇到类似
    http://localhost/DUMMY_SERVICE
    。我必须使用
    HttpListener
    来创建虚拟服务。注意这是如何变得比测试中的代码更复杂。。。
    System.Runtime.Serialization.SerializationException: Member '_HttpRequestHeaders' was not found.
       at System.Runtime.Serialization.SerializationInfo.GetElement(String name, Type& foundType)
       at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
       at System.Net.HttpWebRequest..ctor(SerializationInfo serializationInfo, StreamingContext streamingContext)
       at UnitTests.MockWebRequest..ctor(String responseJson)
       at UnitTests.MockWebRequestCreator.Create(Uri uri)
       at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
       at System.Net.WebRequest.Create(Uri requestUri)
       at code under test