运行测试时,HttpResponseBase.Headers为空
我正在使用Moq创建一个Mock
来测试我正在为我的MVC2应用程序创建的FileResult
。
在FileResult
的WriteFile(HttpResponseBase response)
方法中,我在最后有以下代码:
// Write the final output with specific encoding. response.OutputStream.Write(output, 0, output.Length); response.AppendHeader("Content-Encoding", encoding);
它将使用utf-8
或gzip
具体取决于请求的Accept-Encoding
标头中Accept-Encoding
。
那么在我的测试中,我设置了我的Mock
如下所示:
var mockResponse = new Mock(); mockResponse.Setup(r => r.OutputStream).Returns(new MemoryStream()); mockResponse.Setup(r => r.Headers).Returns(new NameValueCollection());
但是,当我实际检查标头已设置时, Content-Encoding
始终返回null:
var response = mockResponse.Object; Assert.AreEqual("utf-8", response.Headers["Content-Encoding"]);
奇怪的是,OutputStream获取写入它的数据,我可以声明它正在写入正确的值。
奇怪的是,当我实际调试Web项目中的FileResult
时,标头被正确发送。
有没有人对此有所了解? 如有必要,我可以提供更多代码。
我最后只是AppendHeader
了AppendHeader
方法,强行将标头添加到HttpResponseBase
的头文件中:
mockResponse .Setup(r => r.AppendHeader(It.IsAny(), It.IsAny ())) .Callback((string k, string v) => mockResponse.Object.Headers.Add(k, v));
我怀疑在AppendHeader
的调用中还有一些东西不喜欢在没有实际的HttpResponseBase
情况下添加头文件。
如果有更好的主意,请随时提出建议。 希望这可以帮助将来的某个人。
您遇到的问题与您尝试部分模拟HttpResponseBase
类的事实有关。 写入输出流是有效的,因为属性(在本例中为OutputStream
)被模拟并从SUT(被测系统)访问。
但是,当您模拟Headers
属性时,只有该属性被模拟而不是AppendHeader
,这是您的SUT实际执行的操作。 Moq创建的默认模拟只是将所有方法和属性存根为返回默认值,因此AppendHeader
实际上不会执行任何操作。
有两种解决方案,第一种是纯粹的交互测试,是我的首选方法。 不要模拟Headers
,而是validationAppendHeader
。
Mock responseMock = new Mock (); //the rest of response setup FileResult sut = new MyFileResult(); sut.WriteFile(responseMock.Object); responseMock.Verify(response=>response.AppendHeader("Content-Encoding", "utf8"));
第二种方法是利用Moq的部分模拟,这将使模拟对象调用实际类的方法,除非它们已被明确设置。
Mock responseMock = new Mock (){ CallBase = true }; //the rest of response setup FileResult sut = new MyFileResult(); sut.WriteFile(responseMock.Object); Assert.AreEqual("utf-8", responseMock.Object.Headers["Content-Encoding"]);
当您测试与框架的交互时,我更倾向于使用第一个版本。 第二个版本更像是基于状态的测试,所以理论上你甚至不需要模拟,你可以只使用实际的类。 但是,在HttpResponseBase
情况下,它的构造函数受到保护几乎是有意义的,因此通过创建一个模拟,你基本上是从内联派生的,而不必手动编写测试double。
基于提供的设置代码(不确定它是否是一个错字),我认为它应该如下所示
var Response = new Mock(); Response.Setup(r => r.OutputStream).Returns(new MemoryStream()); Response.Setup(r => r.Headers).Returns(new NameValueCollection());