我正在尝试为将HttpResponse对象作为参数的方法创建单元测试。这样做的正确方法是什么?我希望你经验丰富的单位测试人员可以帮助我。
其他信息: 我尝试通过传入StringWriter创建一个假的HttpResponse对象。
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HttpResponse response = new HttpResponse(sw);
RssGenerator.Generate(response, otherParameters);
测试失败并显示以下消息: System.Web.HttpException:使用自定义TextWriter时,OutputStream不可用。正在测试的方法是类库dll的一部分。它使用Response对象的OutputStream来创建带有XMLWriter的RSSFeed。
答案 0 :(得分:12)
需要使用命名空间System.Web.Abstractions
特别是,将HttpResponseBase(http://msdn.microsoft.com/en-us/library/system.web.httpresponsebase.aspx)作为输入参数而不是HttpResponse。然后你可以从测试中模拟HttpResponseBase。当你有一个真正的HttpResponse传入时,使用HttpResponseWrapper来产生一个HttpResponseBase。
答案 1 :(得分:3)
要成为真正的单位,你应该模拟HttpResponse和其他一切只测试你的方法代码。我不知道任何C#模拟实用程序,但是question might help。
然后你可以做这样的事情(例如Java和Mockito):
HttpResponse response = mock(HttpResponse.class);
OutputStream outputStream = mock(OutputStream.class);
when(response.getOutputStream()).thenReturn(outputStream);
RssGenerator.generate(response, otherParameters);
当然,您可能需要更多地配置您的模拟,但您可以获得一般的想法。
答案 2 :(得分:2)
如果你想要一个更详细的答案,这就是我在项目中所做的事情:
_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));
其中SendStringAsHttpResponse定义为
public static void SendStringAsHttpResponse(string data, HttpResponseBase response)
答案 3 :(得分:1)
HttpResponse
的构造函数不适合您使用,它仅用于ASP.NET页面循环,因此没有关于如何创建它的文档。
您必须设置HttpResponse
对象,以便它使用HttpWriter
,否则它将不允许您访问基础流。但是,构造函数将_httpWriter
变量设置为null
,因此您必须找到一些其他方法来设置它。
您可以使用.NET Reflector程序在HttpResponse
课程中进行挖掘,看看它的作用。
答案 4 :(得分:1)
所以Mocking HttpResponse的问题在于它是密封的,因此你无法扩展它(大多数模拟框架,Mock具体类只是覆盖虚拟方法)。微软也很友好,不能为大多数这些提供接口......所以感谢MS。
由于这个原因(其中包括),我通常最终为所有密封的MS类编写自己的接口,然后编写包含构造函数中的MS类的包装器实现,并在请求中尽快将它们分流。然后你可以创建接口的模拟,并让它们做你喜欢的任何事情。
答案 5 :(得分:0)
如果我无法重构方法签名(也许该方法实际上只需要来自HttpResponse的一个值?),我会让Eclipse生成HttpResponse的null实现(是的,我是Java,但它是一样的想法) - 即实现返回null的所有方法 - 只需在待测方法中填入只是我需要的方法,并让它们返回一些常量值。 (是的,也可以使用某种类型的模拟框架。)
您无法创建自己的现有实现实例的原因是它将严重依赖于您的应用程序服务器,并且可能需要各种其他的gunk甚至可以实例化。
如果事实证明我需要比HttpResponse的简单null版本更复杂的东西,那么我会考虑不直接测试这个方法:也许一个或两个级别的测试会更简单并且会为我提供相同级别的对代码的信心。