2010-11-02 4 views
2

Я пишу тестовый пример против контроллера, который возвращает файл PDF.Пробное тестирование ASP.NET MVC Moq против контроллера, который возвращает FileStreamResult

Код для контроллера:

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"); 
    } 

Unit код теста:

[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 равна нулю.

Кто-нибудь знает, как написать единичный тестовый пример против этого типа контроллера?

Большое спасибо!

Джефри

ответ

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"); 
} 
+0

Спасибо большое, это работает perfeclty! – jeffreychi

1

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

Смысл HTTP-контекста был серьезной проблемой в эпоху веб-форм ASP.Net. Возможно, ваш тест должен быть сосредоточен на HelpPageBusinessService.

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

+0

Большое спасибо за ваш ответ, я вполне согласен с вами. Фактически, я уже подготовил тестовый пример против «HelpPageBusinessService». Именно из-за стандартов кода проекта требуется 80% -ное тестирование модулей, я должен написать тестовый пример против этого контроллера. :) – jeffreychi

3

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

[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(); 
     } 
    } 
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"));