2011-05-12 63 views
0

所有,MVC 3單元測試 - 獲取實際響應數據

我開發和單元測試使用ASP.NET MVC 3,其控制器返回一個包含語音XML瀏覽交互式語音應用。我想創建捕獲實際VoiceXML輸出的單元測試,以便我可以對它進行模式驗證。

我的閱讀和測試將我帶到了使用Moq的Scott H的FakeHttpContext以及這裏的幾個回覆。一切編譯正確,我試圖做類似如下:

[TestMethod] 
public void WelcomeTest1() 
{ 
    EmergencyController controller = new EmergencyController(); 
    controller.ControllerContext = new ControllerContext(MvcMockHelpers.FakeHttpContext("~/Emergency/Welcome"), new RouteData(), controller); 

    ViewResult result = (controller.Welcome()) as ViewResult; 
. 
. 
    Assert.IsTrue(controller.ControllerContext.HttpContext.Response.OutputStream.Length > 0); 
    // assert schema validation on the output here 
} 

然而,通過這個步進,我可以看到Welcome視圖被調用,但是我正在尋找的東西迴應。輸出並沒有發現任何東西。模擬設置如下,希望將CallBase設置爲true將實際寫出一些東西。我發現一些代碼,我加入到FakeHttpContext構造,理應調用StringWriter的,但無濟於事:

public static HttpContextBase FakeHttpContext() 
{ 
    var context = new Mock<HttpContextBase>(); 
    var request = new Mock<HttpRequestBase>() { CallBase = true }; 
    var response = new Mock<HttpResponseBase>(); 
    var session = new Mock<HttpSessionStateBase>(); 
    var server = new Mock<HttpServerUtilityBase>(); 

    context.Setup(ctx => ctx.Request).Returns(request.Object); 
    context.Setup(ctx => ctx.Response).Returns(response.Object); 
    context.Setup(ctx => ctx.Session).Returns(session.Object); 
    context.Setup(ctx => ctx.Server).Returns(server.Object); 
    response.Setup(r => r.OutputStream).Returns(new MemoryStream()); 
    response.Setup(r => r.Headers).Returns(new NameValueCollection());   

    var writer = new StringWriter(); 
    var wr = new SimpleWorkerRequest("", "", "", "", writer);   
    HttpContext.Current = new HttpContext(wr); 

    return context.Object; 
} 

我敢肯定,我失去了一些東西很明顯,但現在我很爲難。

感謝

吉姆·斯坦利

黑板連接

回答

0

結果沒有得到填充在的ViewResult。換句話說,視圖不是由您在控制器中調用return View()呈現的,而是mvc獲取viewresult並稍後在request-sycle中呈現它。你需要做的就是爲ViewResults創建一個渲染功能,像這樣的:

using System; 
using System.IO; 
using System.Web.Mvc; 

namespace CoPrice.Helpers 
{ 
    public static class ViewRendrer 
    { 
     public static string ToHtml(this ViewResult result, Controller controller) 
     { 
      controller.ViewData.Model = result.Model; 
      try 
      { 
       using (StringWriter sw = new StringWriter()) 
       { 
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, result.ViewName); 
        ViewContext context = new ViewContext(controller.ControllerContext, viewResult.View, result.ViewData, result.TempData, sw); 
        viewResult.View.Render(context, sw); 

        return sw.GetStringBuilder().ToString(); 
       } 
      } 
      catch (Exception e) 
      { 
       return e.ToString(); 
      } 
     } 
    } 
} 

然後,你可以做result.ToHtml(控制器)獲取的實際數據(這適用於RazorViews只是我覺得,儘管我不確定,但至少我已經使用過)。

+0

Hmmmm,幾乎 - 但下面的代碼彈出,因爲控制器上下文爲null: [TestMethod的] 公共無效WelcomeTest1() { EmergencyController控制器=新EmergencyController(); ViewResult result =(controller.Welcome())as ViewResult; string xml = ViewRenderer.ToHtml(result,controller); Assert.IsTrue(xml.Length> 0); } 我也嘗試從我訪問的其他地方添加FakeControllerContext()代碼,但它也是炸彈,因爲控制器上下文的RouteData()部分僅僅是一個新的RouteData()。 – 2011-05-13 01:16:49

+0

哦,對。我也曾經遇到這個問題......如果我沒有弄錯,你需要大量的嘲弄才能完成所有工作,但這確實是可能的。我沒有代碼,也沒有意願/時間(遺憾)來重寫它,因爲這是很多工作,但如果你做一些google'ing,你可能會找到答案。我在我看到的控制器中使用了這個ToHtml函數,並且在那裏它應該如此。 – Alxandr 2011-05-13 02:13:14

+0

謝謝。我懷疑(希望)RouteValues()將是我需要的最後一件事。希望我可以從應用程序中獲取實際的路由值。非常感謝*擴展方法 - 總是很好地提高我的知識。 – 2011-05-13 16:29:45