Модульное тестирование ASP.NET MVC Moq на контроллере, который возвращает FileStreamResult - PullRequest
2 голосов
/ 03 ноября 2010

Я пишу контрольный пример для контроллера, который возвращает файл 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 ]

4 голосов
/ 03 ноября 2010

Вам нужно смоделировать 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");
}
3 голосов
/ 03 ноября 2010

Следуя рекомендации Дарина Димитрова, я придумал следующий код.:)

 [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();
        }
    }
1 голос
/ 03 ноября 2010

Это классическая проблема тестирования.Это связано с тем, что это скорее интеграционный тест, а не модульный тест (касающийся файловой системы).

Пересечение контекста HTTP было серьезной проблемой в эпоху веб-форм ASP.Net.При тестировании следует сосредоточиться на HelpPageBusinessService.

Если все остальное не удалось, возможно, передайте вспомогательный класс через внедрение зависимостей в ваш контроллер, который добавляет заголовок или макет с помощью фреймворка.

0 голосов
/ 17 июня 2011

Используя 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"));
...