2012-02-20 70 views
3

我有一个模拟挑战 - 我使用MVC 3与nunit框架,并试图模拟一个控制器有一个HttpPostedFileBase作为参数。控制器签名如下所示:传递一个MVC 3控制器参数的模拟HttpPostedFileBase

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

我建立了我的“文件”参数模拟参考,但抱怨说,它不会采取模仿对象。我猜想我需要为这个场景设置一个ControllerContext,但是我也没有任何运气。对于第一次测试,我只需要HttpPostedFileBase返回一个空文件(在空白文件引用进入的情况下)。我也读过Scott Hanselman关于这个主题的优秀文章(computer Zen)。这似乎是MVC部分中关键句,我担心的是“当你创建自己的ControllerContext时,你将在Webserver外运行时(如在测试中)获得一个动态生成的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]); 

我在被卡住的状态。感谢您向正确的方向提供任何建议或推动。

回答

7

假设你使用真实的视图模型(其用于由控制器的动作,而不是使用的参数的极大数):

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; } 
} 

和与正在试图单元测试动作的控制器:

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个案件涉及:

  • 无效的ModelState =>则返回视图
  • 有效的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],您不应远离目标。是的,我敢打赌2¢这个Assert.IsInstanceOfType在NUnit中有一个等价物。

+0

“人 - 秒”的工作,辉煌 – BozoJoe 2014-04-10 06:01:57