您需要模拟HttpContext。这是一个示例(它是MSTest,但我猜将其移植到NUnit不会太麻烦 - 您只需要重命名一些属性):
[TestMethod]
public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
var sut = new HomeController();
var bytes = new byte[] { 1, 2, 3 };
var fileName = "foobar";
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
var response = MockRepository.GenerateMock<HttpResponseBase>();
httpContext.Expect(x => x.Response).Return(response);
var requestContext = new RequestContext(httpContext, new RouteData());
sut.ControllerContext = new ControllerContext(requestContext, sut);
var actual = sut.PrintCSV(bytes, fileName);
Assert.IsInstanceOfType(actual, typeof(FileContentResult));
var file = (FileContentResult)actual;
Assert.AreEqual(bytes, file.FileContents);
Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
response.AssertWasCalled(
x => x.AppendHeader(
Arg<string>.Is.Equal("Content-Disposition"),
Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
)
);
}
如您所见,这里有一些管道代码来设置测试。个人建议使用MvcContrib.TestHelper,因为它可以简化大部分的管道代码,并且使测试更易读。看看这个:
[TestClass]
public class HomeControllerTests : TestControllerBuilder
{
private HomeController sut;
[TestInitialize]
public void TestInitialize()
{
this.sut = new HomeController();
this.InitializeController(this.sut);
}
[TestMethod]
public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
var bytes = new byte[] { 1, 2, 3 };
var fileName = "foobar";
var actual = sut.PrintCSV(bytes, fileName);
var file = actual.AssertResultIs<FileContentResult>();
Assert.AreEqual(bytes, file.FileContents);
Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
this.HttpContext.Response.AssertWasCalled(
x => x.AppendHeader(
Arg<string>.Is.Equal("Content-Disposition"),
Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
)
);
}
}
现在,测试结果更加清晰,我们可以立即看到初始化阶段、测试方法的实际调用以及断言。
注:尽管如此,我不太明白为什么控制器操作需要将byte数组作为参数传递,只是将其流式返回给客户端。也就是说,为了调用它,客户端需要已经拥有该文件,那么这有什么意义呢?但我想这只是为了说明而已。在您的实际方法中,byte数组并不是作为参数传递的,而是从某个外部依赖项中在您的控制器操作中检索出来的。在这种情况下,您也可以模拟这个依赖项(当然,前提是您已经正确设计了层次结构,并且它们足够弱耦合)。