单元测试一个文件上传,如何?

Posted

技术标签:

【中文标题】单元测试一个文件上传,如何?【英文标题】:Unit Test a file upload, how? 【发布时间】:2012-01-08 16:23:13 【问题描述】:

使用 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,但我正在努力弄清楚如何“伪造”文件上传,并且我也很警惕我已经设法做到的起订量示例find now 似乎已弃用其中的代码。

我只是想知道如何模拟 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,因为能够“模拟”一个是我试图关注这个问题的目的。

【问题讨论】:

见问题***.com/questions/5515404/… 我希望能够将一个对象从我的测试方法传递到方法中,这将允许我测试其中的代码,所以我想从测试方法中执行此操作:controller.UploadFile( fakeObjectHereButDontKnowHow)。我认为 Chris Sainty 示例包含许多过时的代码。正如我所说,我一直在为一些起订量的在线材料而苦苦挣扎.. 【参考方案1】:

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

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

【讨论】:

以上是关于单元测试一个文件上传,如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 中对文件上传进行单元测试

如何使用 API 平台对 GraphQL 文件上传进行单元测试?

如何使用 Ivy 构建和单元测试?

HTML5文件上传的单元测试

如何对 Asp.net MVC 文件进行单元测试

Junit 测试文件上传