asp.net-mvc-3 - 将模拟的 HttpPostedFileBase 作为 MVC 3 Controller 参数传递

标签 asp.net-mvc-3 http mocking

我有一个 Mock 挑战 - 我将 MVC 3 与 nunit 框架一起使用,并尝试模拟一个 Controller ,它有一个 HttpPostedFileBase 作为参数。 Controller 签名如下所示:

 public ActionResult UploadAttachment(AttachmentViewModel clientAttachment, HttpPostedFileBase file, string clientName)

我为我的"file"参数设置了一个模拟引用,但它提示说它不会采用模拟对象。我猜我需要为这种情况设置一个 ControllerContext,但我也没有运气。对于第一个测试,我只需要 HttpPostedFileBase 返回一个空文件(在空白文件引用进入的情况下)。我还阅读了 Scott Hanselman 关于此主题的优秀文章 (computer Zen)。对于我来说,MVC 部分中的关键句子似乎是“当您创建自己的 ControllerContext 时,您将在 Web 服务器外部(如测试内部)运行时获得动态生成的 HttpRequestBase 派生模拟。”这似乎是我遇到困难的地方。

我知道我需要这些元素:

controller.ControllerContext = new ControllerContext(mockContext.Object, new RouteData(), controller);
mockContext.SetupGet(c => c.Request).Returns(mockRequest.Object);
mockRequest.Setup(c => c.HttpMethod).Returns([not sure what to evoke here]);

我处于被卡住的状态。感谢您在正确方向上提出的任何建议或插入。

最佳答案

假设您使用真实的 View 模型(由您的 Controller 操作使用,而不是使用大量参数):

public class MyViewModel
{
    public HttpPostedFileBase File { get; set; }

    // those won't be used in my example but you get the point
    public string ClientName { get; set; }
    public AttachmentViewModel ClientAttachment { get; set; }
}

和一个带有您要尝试进行单元测试的操作的 Controller :

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult UploadAttachment(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        var file = Path.Combine(Server.MapPath("~/App_Data"), model.File.FileName);
        model.File.SaveAs(file);
        return RedirectToAction("succes");
    }
}

您现在有 2 个案例要涵盖:

  • 无效的模型状态 => 返回一个 View
  • valid modelstate => 文件已保存,我们已重定向。

让我们开始吧:

[TestMethod]
public void UploadAttachment_Should_Return_View_If_ModelState_Is_Not_Valid()
{
    // arrange
    var sut = new HomeController();
    var model = new MyViewModel();
    sut.ModelState.AddModelError("file", "please select a file");

    // act
    var actual = sut.UploadAttachment(model);

    // assert
    Assert.IsInstanceOfType(actual, typeof(ViewResult));
}

当然还有第二种情况:

[TestMethod]
public void UploadAttachment_Should_Save_File_If_Model_Is_Valid_And_Redirect()
{
    // arrange
    var sut = new HomeController();
    var file = new Mock<HttpPostedFileBase>();
    file.Setup(x => x.FileName).Returns("foo.txt");
    var model = new MyViewModel
    {
        File = file.Object
    };
    var server = new Mock<HttpServerUtilityBase>();
    server.Setup(x => x.MapPath("~/App_Data")).Returns(@"c:\wwwroot\App_Data");
    var httpContext = new Mock<HttpContextBase>();
    httpContext.Setup(x => x.Server).Returns(server.Object);
    sut.ControllerContext = new ControllerContext(httpContext.Object, new RouteData(), sut);

    // act
    var actual = sut.UploadAttachment(model);

    // assert
    Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
    file.Verify(x => x.SaveAs(@"c:\wwwroot\App_Data\foo.txt"));
}

希望这会让您走上正轨。抱歉,它使用 MSTest 而不是 NUnit,但端口应该不仅仅是微不足道的(不应该超过 30 人秒的工作)。将 [TestMethod] 替换为 [Test] ,您应该离目标不远了。是的,我敢打赌这个 Assert.IsInstanceOfType 在 NUnit 中有一个等价物。

关于asp.net-mvc-3 - 将模拟的 HttpPostedFileBase 作为 MVC 3 Controller 参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9369489/

相关文章:

Linq 查询在没有任何明显原因的情况下被多次触发

javascript - node.js 上的客户端 ssl 授权

c++ - 如何使用 google mock 在 C++ 中模拟继承链

spring - 如何在 MockMvc 中从 jsonPath() 中检索字符串

asp.net-mvc - MVC3 Url.Action 查询字符串生成

c# - MVC Razor 隐藏输入和传递值

javascript - 检查 Base64 图像是否经过 gzip 压缩

java - Apache Camel如何以 "body"格式提交正文

asp.net-mvc - 如何模拟 ServiceStackController Cache 属性?

c# - 如何使用 entitystate.modified 更新外键?