2011-11-29 27 views
14

Usando MVC3.NET Tengo un método de carga de archivos en un controlador que funciona bien con la siguiente firma public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> file)Unidad Prueba una carga de archivo, ¿cómo?

¿Cómo puedo unidad de prueba esto con NUnit? He mirado alrededor y todos parecen apuntar a Moq pero soy nuevo en las pruebas unitarias y no puedo hacer que Moq funcione.

He encontrado blogs interesantes como este: http://danielglyde.blogspot.com/2011/07/tdd-with-aspnet-mvc-3-moq-and.html pero estoy luchando para descubrir cómo se podría hacer lo mismo para 'falsificar' una carga de archivos, y también tengo mucho cuidado con ejemplos de moq que he logrado encontrar ahora parecen tener código obsoleto en ellos.

Simplemente me gustaría saber cómo puedo simular un HttpPostedFileBase para poder probar mi código de carga, usando Moq o de otra manera. Estaría muy agradecido si alguien pudiera darme algunos ejemplos de código sobre cómo hacer esto.

El siguiente código tomado de otros ejemplos aquí:

var file = new Mock<HttpPostedFileBase>(); 
      file.Setup(f => f.ContentLength).Returns(1); 
      file.Setup(f => f.FileName).Returns("test.txt"); 

controller.upload(file); 

genera el siguiente error cuando intento compilar:

no se puede convertir de 'Moq.Mock' a 'del sistema. Web.HttpPostedFileBase '

He cambiado el método para tomar un HttpPostedFileBase singular por el momento, en lugar de un IEnumerable , como poder 'burlarse' de uno es en lo que estoy tratando de enfocarme con el propósito de esta pregunta.

+0

Véase la pregunta http://stackoverflow.com/questions/5515404/how-to-unit-test-asp-net-mvc-fileupload – wnascimento

+0

Quiero ser capaz de pasar un objeto en el método de mi método de prueba que me permitirá probar el código dentro de él, así que quiero hacer esto desde un método de prueba: controller.UploadFile (fakeObjectHereButDontKnowHow). El ejemplo de Chris Sainty contiene un montón de código obsoleto, creo. Como dije, he tenido problemas con parte del material en línea para moq ... – DevDave

Respuesta

23

Suponiendo una acción de carga de archivo estándar:

[HttpPost] 
public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> files) 
{ 
    foreach (var file in files) 
    { 
     var filename = Path.Combine(Server.MapPath("~/app_data"), file.FileName); 
     file.SaveAs(filename); 
    } 
    return View(); 
} 

podría probar de esta manera:

[Test] 
public void Upload_Action_Should_Store_Files_In_The_App_Data_Folder() 
{ 
    // arrange 
    var httpContextMock = new Mock<HttpContextBase>(); 
    var serverMock = new Mock<HttpServerUtilityBase>(); 
    serverMock.Setup(x => x.MapPath("~/app_data")).Returns(@"c:\work\app_data"); 
    httpContextMock.Setup(x => x.Server).Returns(serverMock.Object); 
    var sut = new HomeController(); 
    sut.ControllerContext = new ControllerContext(httpContextMock.Object, new RouteData(), sut); 

    var file1Mock = new Mock<HttpPostedFileBase>(); 
    file1Mock.Setup(x => x.FileName).Returns("file1.pdf"); 
    var file2Mock = new Mock<HttpPostedFileBase>(); 
    file2Mock.Setup(x => x.FileName).Returns("file2.doc"); 
    var files = new[] { file1Mock.Object, file2Mock.Object }; 

    // act 
    var actual = sut.UploadFile(files); 

    // assert 
    file1Mock.Verify(x => x.SaveAs(@"c:\work\app_data\file1.pdf")); 
    file2Mock.Verify(x => x.SaveAs(@"c:\work\app_data\file2.doc")); 
} 

Obviamente toda la parte de configuración HttpContext debe exterioriza en una reusable class que podría llamarse en el [SetUp] fase de su unidad de prueba para preparar el contexto simulado del sujeto bajo prueba y evitar repetirlo en cada prueba unitaria.