2011-11-29 38 views
14

使用MVC3.NET我有一个控制器中的文件上传方法,可以很好地处理以下签名public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> file)单元测试文件上传,怎么样?

我该如何使用NUnit对此进行单元测试?我环顾四周,似乎每个人都指向Moq,但我是单元测试新手,无法让Moq工作。

我发现了一些有趣的博客,例如:http://danielglyde.blogspot.com/2011/07/tdd-with-aspnet-mvc-3-moq-and.html,但我正在努力弄清楚如何做同样的事情来伪造一个文件上传,同时也很关心我设法找到的moq示例现在似乎已经废弃了代码。

我只想知道如何模拟一个HttpPostedFileBase,这样我就可以使用Moq或其他方式测试我的上传代码 - 如果有人能给我一些关于如何做到这一点的代码示例,我将非常感激。

其他例子在这里采取下面的代码:

无法从“Moq.Mock”转换为 “系统:

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

controller.upload(file); 

,当我尝试编译生成以下错误。 Web.HttpPostedFileBase'

我改变了现在采用单数HttpPostedFileBase的方法,而不是IEnumerable ,因为能够“模拟”一个就是我试图关注这个问题的目的。

+0

请看问题 http://stackoverflow.com/questions/5515404/how-to-unit-test-asp-net-mvc-fileupload – wnascimento

+0

我希望能够将对象传递到方法,从我测试方法,将允许我测试它里面的代码,所以我想从测试方法:controller.UploadFile(fakeObjectHereButDontKnowHow)做到这一点。克里斯舜天的例子包含了很多过时的代码,我想。正如我所说,我一直在努力与一些在线材料moq .. – DevDave

回答

23

假设一个标准的文件上传动作:

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

,你可以这样测试:

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

显然所有的HttpContext设置部分应具体形式为reusable class,可以在被称为[SetUp]您的单元测试的阶段,准备测试对象的模拟上下文,并避免在每个单元测试中重复它。