2010-11-02 7 views
2

J'écris un scénario de test sur un contrôleur qui renvoie un fichier pdf.Test de l'unité Moq ASP.NET MVC par rapport à un contrôleur qui renvoie FileStreamResult

code pour le contrôleur:

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

code de test unitaire:

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

Ce cas de test unitaire ne fonctionne pas, échoueront comme HttpContext est nulle.

Est-ce que quelqu'un sait comment écrire un cas de test unitaire contre ce type de contrôleur?

Très apprécié!

Jeffery

Répondre

4

Vous devez mock the HttpContext et les objets de réponse. Votre action de contrôleur peut également être raccourcie un peu:

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

Merci beaucoup, il fonctionne parfaitement! – jeffreychi

1

Ceci est un problème de test classique. Cela vient du fait qu'il s'agit plus d'un test d'intégration que d'un test unitaire (touchant le système de fichiers).

La simulation de contexte HTTP a été un problème majeur à l'époque de ASP.Net Web Forms. Votre test devrait peut-être se concentrer sur HelpPageBusinessService.

Si tout le reste échoue peut-être passer une classe d'aide via injection de dépendance à votre contrôleur, qui ajoute l'en-tête ou simulacre avec un cadre moqueur.

+0

Merci beaucoup pour votre réponse, je suis tout à fait d'accord avec vous. En fait, j'ai déjà produit un test sur le "HelpPageBusinessService". C'est juste parce que les normes du code de projet exigent une couverture de 80% des tests unitaires, je dois écrire un cas de test contre ce contrôleur. :) – jeffreychi

3

Suite à la recommandation de Darin Dimitrov, j'ai trouvé le code suivant. :)

[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

En utilisant MOQ, vous pouvez même tester si l'en-tête a été effectivement ajouté à l'objet de réponse

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

Ensuite, vous pouvez vérifier

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