ASP.NET MVC Moq单元测试针对返回FileStreamResult的控制器

时间:2010-11-02 22:32:14

标签: asp.net-mvc unit-testing filestreamresult

我正在针对返回pdf文件的控制器编写测试用例。

控制器代码:

  public FileStreamResult GeneratePdfReport(string context)
    {
        byte[] pdfReportContents = _helpPageBusinessService.GetHelpPagesAsPdf();
        Stream stream = new MemoryStream(pdfReportContents);
        HttpContext.Response.AddHeader("content-disposition", "attachment; filename=GSFA_Help_Pages_Printout.pdf");
        return new FileStreamResult(stream, "application/pdf");
    }

单元测试代码:

 [TestMethod]
    public void GeneratePdf()
    {
        var controller = new HelpController(_helpPageBusinessServiceReportServices, Logger);
        try
        {
            var result = controller.GeneratePdfReport("Work_Request_Section");
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.FileStream);
        }
        finally
        {
            controller.Dispose();
        }
    }

这个单元测试用例不起作用,它总是失败,因为HttpContext为null。

有没有人知道如何针对这种类型的控制器编写单元测试用例?

非常感谢!

杰弗里

4 个答案:

答案 0 :(得分:4)

您需要mock the HttpContext和响应对象。您的控制器操作也可以缩短一点:

public ActionResult GeneratePdfReport(string context)
{
    byte[] pdfReportContents = _helpPageBusinessService.GetHelpPagesAsPdf();
    HttpContext.Response.AddHeader("content-disposition", "attachment; filename=GSFA_Help_Pages_Printout.pdf");
    return File(pdfReportContents, "application/pdf");
}

答案 1 :(得分:3)

根据Darin Dimitrov的建议,我提出了以下代码。 :)

 [TestMethod]
    public void GeneratePdf()
    {
        var controller = new HelpController(_helpPageBusinessServiceReportServices, Logger);
        var httpContextBase = new Mock<HttpContextBase>
        {
            DefaultValue = DefaultValue.Mock
        };
        var responseObject = Mock.Get(httpContextBase.Object.Response);
        responseObject.Setup(
            s => s.AddHeader("content-disposition", "attachment; filename=GSFA_Help_Pages_Printout.pdf"));
        controller.ControllerContext = new ControllerContext(httpContextBase.Object, new RouteData(), controller);
        try
        {
            var result = controller.GeneratePdfReport("Work_Request_Section");
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.FileStream);
            Assert.IsTrue(result.FileStream.Length == 2000);
        }
        finally
        {
            controller.Dispose();
        }
    }

答案 2 :(得分:1)

这是一个经典的测试问题。它源于这一事实,它更多的是集成测试,而不是单元测试(触摸文件系统)。

模拟HTTP上下文一直是ASP.Net Web Forms时代的一个主要问题。也许你的测试应该关注于HelpPageBusinessService。

如果所有其他方法都失败了,可能会通过依赖注入将助手类传递给控制器​​,这会将标头或模拟添加到模拟框架中。

答案 3 :(得分:0)

使用MOQ,您甚至可以测试标头是否已实际添加到响应对象

var httpContextBase = new Mock<HttpContextBase>();
_httpResponse = new Mock<HttpResponseBase>();
httpContextBase.Setup(c => c.Response).Returns(_httpResponse.Object);
controller = new Controller(businessService.Object)
{
     ControllerContext = new ControllerContext { HttpContext = httpContextBase.Object }
};

然后你可以验证

_httpResponse.Verify(r => r.AddHeader("content-disposition", "attachment; filename=GSFA_Help_Pages_Printout.pdf"));