2012-02-20 75 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