Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何为单元测试填充HttpWebResponse.GetResponseAsync()?_C#_Unit Testing_Mocking_Httpwebrequest_Microsoft Fakes - Fatal编程技术网

C# 如何为单元测试填充HttpWebResponse.GetResponseAsync()?

C# 如何为单元测试填充HttpWebResponse.GetResponseAsync()?,c#,unit-testing,mocking,httpwebrequest,microsoft-fakes,C#,Unit Testing,Mocking,Httpwebrequest,Microsoft Fakes,我被指派为一个我无权修改的应用程序编写单元测试。我想要进行单元测试的方法进行如下调用: HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse; 在这个项目中,我已经使用微软的Fakes进行了数千次其他测试,所以我想我在这里也会这样做。在我看来,最简单、最干净的解决方案似乎是填充request.GetResponseAsync()方法。然后我可以返回一些假内容,并确保该方法在不发出请求的情况下

我被指派为一个我无权修改的应用程序编写单元测试。我想要进行单元测试的方法进行如下调用:

HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
在这个项目中,我已经使用微软的Fakes进行了数千次其他测试,所以我想我在这里也会这样做。在我看来,最简单、最干净的解决方案似乎是填充
request.GetResponseAsync()
方法。然后我可以返回一些假内容,并确保该方法在不发出请求的情况下正确处理它

GetResponseAsync()
返回一个
Task
对象。所以我通常会这样做:

using (ShimsContext.Create())
{
    System.Net.Fakes.ShimWebRequest.AllInstances.GetResponseAsync = (x) =>
    {
        return new Task<WebResponse>(() =>
        {
            HttpWebResponse toRet = new HttpWebResponse();
            return toRet;
        });
    }
}
使用(ShimsContext.Create())
{
System.Net.Fakes.ShimWebRequest.AllInstances.GetResponseAsync=(x)=>
{
返回新任务(()=>
{
HttpWebResponse toRet=新的HttpWebResponse();
返回托雷特;
});
}
}
问题是上面的代码无法编译,因为

'System.Net.HttpWebResponse.HttpWebResponse()'已过时:'此API 支持.NET Framework基础架构,不打算 直接从代码中使用。”


我知道这个类型已经过时了,我们现在应该使用一些不同的东西,但是我尝试测试的遗留代码不允许我这么奢侈。我看了很多关于这个话题的问题,但似乎没有一个能回答这个问题。

你的问题与Shim无关。使用反射绕过过时的问题

HttpWebResponse toRet = Activator.CreateInstance<HttpWebResponse>();
HttpWebResponse toRet=Activator.CreateInstance();

我将我的答案分成两部分;第一部分是您正在寻找的解决方案。。。在第二部分中,我将讨论UT环境中的其他选项(因此这个答案将帮助其他人…)

因为您已经使用了MsFakes,所以可以使用它创建一个实例。 下面的代码段是一个示例,显示了初始化和使用
ShimHttpWebResponse
的方法:

[Test]
public async Task InitializeShimHttpWebResponse()
{
    using (ShimsContext.Create())
    {
        ShimWebRequest.AllInstances.GetResponseAsync = (x) =>
        {
/* you can replace the var with WebResponse if you aren't going to set any behavior */
            var res = new ShimHttpWebResponse(); 
            return Task.FromResult((WebResponse)res);
        };

        ShimWebRequest.CreateString = uri =>
        {
            WebRequest req = new ShimFileWebRequest();
            return req;
        };

        var request = WebRequest.Create("");
        var response = await request.GetResponseAsync() as HttpWebResponse;

        Assert.IsNotNull(response);
    }
}
赝品配置:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="System" Version="4.0.0.0"/>
  <ShimGeneration>
    <Add FullName="System.Net.HttpWebResponse"/>
    <Add FullName="System.Net.WebRequest"/>
    <Add FullName="System.Net.HttpWebRequest"/>
    <Add FullName="System.Net.FileWebRequest"/>    
  </ShimGeneration>
</Fakes>

,)

要使用内部\公共命令,您必须使用反射,但在大多数情况下,反射无法开箱即用,然后您必须违反一些UT规则(小、快等)

以下两种情况下,反射将立即生效:

  • 您不需要在实例上调用任何有问题的属性/方法,SUT(测试中的主题)只需将此实例传递给他的一个依赖项

  • 您将使用更多反射来初始化实例字段

  • 虽然第一个是一个简单的案例(如果这是你的案例,那么你应该使用反射),但第二个在UT环境中是一个不好的实践;您的UTs不会很小/可读/可维护,执行时间会增加,Microsoft可能会进行一些重构,这可能会破坏您的UTs

    对于受保护的一个,您应该通过继承(编译与运行时…)调用它

    2。继承:

    受保护的C'tor还具有过时属性,但是属性设置为false,这允许您继承此类,然后您将能够更改方法/属性的行为;虚拟-重写,非虚拟-仅当您有权访问类成员(或反射)时

    此选项的主要缺点是必须生成的代码量和复杂性

    3。使用基于代理的框架:

    在场景背后,这些工具使用反射基于类创建继承的实例(组合选项1和2) 这些工具有一些内置方法,可以使伪代码更小/可读/可维护

    缺点:(我不会指出基于代理的工具的所有缺点…)

  • 您仍然无法更改非虚拟方法的行为

  • 您没有访问实例成员的权限

  • 这两个问题可以通过使用代码编织工具来解决

    4。代码编织工具:

    这些工具几乎可以让你做任何事情,这就是为什么这些工具在一般情况下是最好的(我可以用这句话总结主要的缺点-强大的力量带来巨大的责任…)。 在你的情况下,他们为你提供了最好的解决方案; 由于
    HttpWebResponse
    有一个非虚拟方法,并且您不想重构代码,因此这是适合您的正确解决方案


    但是,Msfakes没有为您提供UT的附加方法/功能(
    AssertSwascaled
    、计数等),因此,除非您打算用其他工具替换该工具,否则在我看来,您应该将其与代理基础工具(免费工具)结合起来。

    无论我尝试过什么,我都无法生成ShimXXX类。我正在尝试。我通过简单地关闭VS2019,打开,清理项目,重建项目来修复我的问题