Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.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/1/asp.net/37.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# 将HttpResponse对象作为参数的方法的单元测试。OutputStream不可用_C#_Asp.net_.net_Unit Testing - Fatal编程技术网

C# 将HttpResponse对象作为参数的方法的单元测试。OutputStream不可用

C# 将HttpResponse对象作为参数的方法的单元测试。OutputStream不可用,c#,asp.net,.net,unit-testing,C#,Asp.net,.net,Unit Testing,我正在尝试为一个将HttpResponse对象作为参数的方法创建一个单元测试。正确的做法是什么?我希望你们这些经验丰富的单元测试人员能帮助我 其他信息: 我试图通过传入StringWriter来创建一个假的HttpResponse对象 StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); HttpResponse response = new HttpResponse(sw); RssGen

我正在尝试为一个将HttpResponse对象作为参数的方法创建一个单元测试。正确的做法是什么?我希望你们这些经验丰富的单元测试人员能帮助我

其他信息: 我试图通过传入StringWriter来创建一个假的HttpResponse对象

StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HttpResponse response = new HttpResponse(sw);
RssGenerator.Generate(response, otherParameters);

测试失败,消息为:System.Web.HttpException:OutputStream在使用自定义TextWriter时不可用。正在测试的方法是类库dll的一部分。它使用响应对象的OutputStream创建带有XMLWriter的RSSFeed

要成为真正的单元,您应该模拟HttpResponse和其他一切,只测试您的方法代码。我不知道有哪种C#mock实用程序,但是这个

然后您可以执行类似的操作(示例是带有Mockito的Java):


当然,您可能需要配置更多的mock,但您已经了解了总体思路。

HttpResponse的构造函数不是供您使用的,它只供ASP.NET页面循环使用,因此没有关于如何创建的文档

您必须设置
HttpResponse
对象,以便它使用
HttpWriter
,否则它将不允许您访问底层流。但是,构造函数将
\u httpWriter
变量设置为
null
,因此您必须找到其他方法来设置它


您可以使用该程序在
HttpResponse
类中挖掘,看看它能做什么。

如果我不能重构方法签名(也许该方法真的只需要来自HttpResponse的一个值?),我会让Eclipse生成HttpResponse的空实现(是的,我使用Java,但这是相同的想法)--即,实现所有返回null的方法--只需在要测试的方法中填写我需要的方法,并让它们返回一些常量值。(是的,也可以使用某种模拟框架。)

您无法创建现有实现的自己的实例的原因是,它将与您的应用程序服务器紧密关联,并且可能需要各种其他的gunk来实例化


如果结果证明我需要比简单的HttpResponse空版本更复杂的东西,然后我会考虑不直接测试这个方法:也许一个或两个级别的测试会更简单,并且会为我提供相同级别的代码信心。

所以模拟HttpResponse的问题是它是密封的,所以你不能扩展它(大多数模拟具体类的模拟框架只是覆盖虚拟方法). 微软也很好心,没有为其中的大多数提供接口…所以,谢谢微软


出于这个原因(除其他原因外),我通常会为所有密封的MS类编写自己的接口,然后编写包装器实现,在构造函数中使用MS类,并在请求中尽快将其分流。然后,您可以创建接口的模拟,并让它们做任何您喜欢的事情。

需要使用namespace System.Web.Abstractions


特别是,将HttpResponseBase()作为输入参数,而不是HttpResponse。然后可以从测试中模拟HttpResponseBase。当您要传入一个真正的HttpResponse时,请使用HttpResponseWrapper生成一个HttpResponseBase。

如果您想要更详细的答案,下面是我在项目中结束时所做的:

_mockResponse = new Mock<HttpResponseBase>();
_contentType = string.Empty;
_mockResponse.SetupSet(r => r.ContentType = It.IsAny<string>()).Callback<string>(value => _contentType = value);
_header = new KeyValuePair<string, string>();
_mockResponse.Setup(r => r.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback((string name, string value) => _header = new KeyValuePair<string, string>(name, value));
_writer = new StringBuilder();
_mockResponse.Setup(r => r.Write(It.IsAny<string>())).Callback<string>(s => _writer.Append(s));
var data = "This is the string to send as response";

UTIL.SendStringAsHttpResponse(data, _mockResponse.Object);

Assert.That(_contentType, Is.EqualTo("application/CSV"));
Assert.That(_header.Value, Is.EqualTo("attachment; filename=download.csv"));
Assert.That(_writer.ToString(), Is.EqualTo(data));

谢谢你所有的好答案。我会让你知道我最终会怎么做。我花了一段时间才找到这个,所以它是:HttpResponseWrapper=newHttpResponseWrapper(this.Response);就是如何做你所描述的。HttpResponseWrapper扩展了HttpResponseBase。您是如何实现SendString方法的?这似乎是这里的关键;)至少我不明白。
_mockResponse = new Mock<HttpResponseBase>();
_contentType = string.Empty;
_mockResponse.SetupSet(r => r.ContentType = It.IsAny<string>()).Callback<string>(value => _contentType = value);
_header = new KeyValuePair<string, string>();
_mockResponse.Setup(r => r.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback((string name, string value) => _header = new KeyValuePair<string, string>(name, value));
_writer = new StringBuilder();
_mockResponse.Setup(r => r.Write(It.IsAny<string>())).Callback<string>(s => _writer.Append(s));
var data = "This is the string to send as response";

UTIL.SendStringAsHttpResponse(data, _mockResponse.Object);

Assert.That(_contentType, Is.EqualTo("application/CSV"));
Assert.That(_header.Value, Is.EqualTo("attachment; filename=download.csv"));
Assert.That(_writer.ToString(), Is.EqualTo(data));
public static void SendStringAsHttpResponse(string data, HttpResponseBase response)