c# - 运行测试时 HttpResponseBase.Headers 为空

标签 c# asp.net-mvc unit-testing moq

我正在使用 Moq 创建一个 Mock<HttpResponseBase>测试 FileResult我正在为我的 MVC2 应用程序创建。

WriteFile(HttpResponseBase response) FileResult 的方法,最后我有以下代码:

// Write the final output with specific encoding.
response.OutputStream.Write(output, 0, output.Length);
response.AppendHeader("Content-Encoding", encoding);

它将使用 utf-8gzip取决于请求的 Accept-Encoding 的编码标题。

然后在我的测试中,我设置了我的 Mock<HttpResponseBase>像这样:

var mockResponse = new Mock<HttpResponseBase>();
mockResponse.Setup(r => r.OutputStream).Returns(new MemoryStream());
mockResponse.Setup(r => r.Headers).Returns(new NameValueCollection());

但是当我实际检查标题是否已设置时,Content-Encoding 总是返回空值:

var response = mockResponse.Object;
Assert.AreEqual("utf-8", response.Headers["Content-Encoding"]);

奇怪的是 OutputStream 得到了写入它的数据,我可以断言它正在写入正确的值。

奇怪的是,当我实际调试 FileResult 时在 Web 项目中, header 已正确发送。

有没有人对此有所了解?如有必要,我可以提供更多代码。

最佳答案

您遇到的问题与您试图部分模拟 HttpResponseBase 类这一事实有关。写入输出流是可行的,因为该属性(在本例中为 OutputStream)被模拟并从 SUT(被测系统)访问。

但是,当您模拟 Headers 属性时,只会模拟该属性,而不是 AppendHeader,这是您的 SUT 实际执行的操作。 Moq 创建的默认模拟只是将所有方法和属性作为返回默认值 stub ,因此 AppendHeader 实际上不执行任何操作。

对此有两种解决方案,第一种是纯粹的交互测试,这是我的首选方法。不要模拟 Headers,而是验证 AppendHeader

Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>();
//the rest of response setup
FileResult sut = new MyFileResult();
sut.WriteFile(responseMock.Object);
responseMock.Verify(response=>response.AppendHeader("Content-Encoding", "utf8"));

第二种方法是利用 Moq 的部分模拟,这将使模拟对象调用实际类的方法,除非它们已被显式设置。

Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>(){ 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 的情况下,它几乎是有意义的,因为它的构造函数是 protected ,因此通过创建模拟,您基本上是从它内联派生的,而无需手动编写测试替身。

关于c# - 运行测试时 HttpResponseBase.Headers 为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4066184/

相关文章:

c# - 查找多维数组中仅第一维的长度

c# - 是否可以更改匿名类型?

C#/IIS/MVC : Static Conetent not loading on different environments

javascript - 如何对这段代码进行单元测试

c# - 正则表达式将字符串中的日期与 where 子句匹配

c# - 在.Net 2.0 的另一个线程中加载表单?

c# - 将 ViewModel 与包含 HttpPostedFileBase 的 ViewModel 列表绑定(bind)到 Controller 操作

asp.net-mvc - 我可以在不加载整个集合的情况下删除单个子实体吗?

unit-testing - 如何使用Spock框架测试Grails服务方法的交互

javascript - 使用 karma 测试 angularjs 时初始化 Controller 时出错