单元测试文件上传,怎么样?

时间:2011-11-29 10:02:33

标签: asp.net-mvc-3 file testing upload moq

使用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或其他方式测试我的上传代码 - 如果有人能给我一些关于如何执行此操作的代码示例,我将非常感激。

以下代码来自其他示例:

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

controller.upload(file);
我尝试编译时

生成以下错误:

  

无法从'Moq.Mock'转换为   'System.Web.HttpPostedFileBase'

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

1 个答案:

答案 0 :(得分:24)

假设标准文件上传操作:

[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]阶段调用,以准备被测试对象的模拟上下文并避免重复它在每个单元测试中。