2010-03-22 115 views
30

有人能告訴我你將如何去創建一個模擬HTML助手與Moq?如何用Moq單元測試HtmlHelper?

article有一個鏈接到一篇文章,聲稱來形容這一點,但僅之後返回一個ASP.NET運行時錯誤的鏈接

[編輯] 我問有關同一主題的一個更具體的問題here,但沒有得到任何迴應。我認爲它太具體了,所以我認爲我可以對一個更一般的問題得到更一般的答案,並對其進行修改以滿足我的要求。

感謝

+0

你能否提供一些代碼正在測試? – 2010-03-22 21:39:22

+0

@Samuel,相關的代碼在我編輯時鏈接到的問題中。 – DaveDev 2010-03-22 22:10:52

+0

我實際上並不知道一個好的答案(不記得C#的細節),但是我試圖獲得一些注意力。=) – 2010-03-22 23:05:21

回答

10

你可以做的是這樣的:

HtmlHelper helper = null; 
helper.YourHelperMethod(); 

無需要嘲笑任何東西。對我而言非常出色。

+28

這隻有在你編寫了一個完全不使用助手的助手方法時纔有效。如果您嘗試訪問'ViewContext','RouteCollection'或其他任何內容,都無濟於事。 – 2012-08-17 13:33:29

+3

這不應該被接受的答案。它只回答一個場景,而不是你必須使用Html Helper的情況。就像@MattEnright所說的那樣,如果您需要使用測試Html Helper來生成Action Link,它不會對您有所幫助。 – 2014-04-19 22:23:31

+1

這顯然是一個嘲弄的答案 - ) – trailmax 2014-11-11 11:37:27

41

Here的另一篇文章,告訴您如何來實現同樣的事情:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd) 
{ 
    var mockViewContext = new Mock<ViewContext>(
    new ControllerContext(
     new Mock<HttpContextBase>().Object, 
     new RouteData(), 
     new Mock<ControllerBase>().Object), 
    new Mock<IView>().Object, 
    vd, 
    new TempDataDictionary()); 

    var mockViewDataContainer = new Mock<IViewDataContainer>(); 
    mockViewDataContainer.Setup(v => v.ViewData).Returns(vd); 

    return new HtmlHelper(mockViewContext.Object, mockViewDataContainer.Object); 
} 
+5

這應該是被接受的答案。這個對象實際上是在這裏嘲笑的。 – SandRock 2014-02-01 17:16:33

+2

此代碼僅適用於MVC4,不適用於MVC5。 – 2014-04-19 21:00:43

+1

我對MVC5進行了更改。等待同行評議。 – bradlis7 2015-09-25 15:30:02

18

在MVC5中,ViewContext具有TextWriter的額外構造函數參數,因此Thomas的代碼不再有效。我加了一個內存中的TextWriter來解決這個問題:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd) 
{ 
    Mock<ViewContext> mockViewContext = new Mock<ViewContext>(
     new ControllerContext(
      new Mock<HttpContextBase>().Object, 
      new RouteData(), 
      new Mock<ControllerBase>().Object 
     ), 
     new Mock<IView>().Object, 
     vd, 
     new TempDataDictionary(), 
     new StreamWriter(new MemoryStream()) 
    ); 

    Mock<IViewDataContainer> mockDataContainer = new Mock<IViewDataContainer>(); 
    mockDataContainer.Setup(c => c.ViewData).Returns(vd); 

    return new HtmlHelper(mockViewContext.Object, mockDataContainer.Object); 
} 
+2

MVC4也需要此版本的代碼 – John 2014-02-11 11:24:19

+0

要使用ViewBag,我將方法簽名更改爲'public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd,object clientData)',並將返回行更改爲'var htmlHelper = new HtmlHelper(mockViewContext.Object,mockViewDataContainer 。目的); htmlHelper.ViewBag.Client = clientData; return htmlHelper;' – LosManos 2014-02-26 15:11:22

+0

這是迄今爲止最好的答案,但如果你有一個使用htmlHelper的html helper,它將不起作用。例如,如果您使用Html.action(...),則會生成一個空答案。 – 2014-04-19 22:25:02

1

爲了測試一次性幫手像BeginForm與訪問ViewContext.Writer您可以使用此:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd, Stream stream = null) 
{ 
    TextWriter textWriter = new StreamWriter(stream ?? new MemoryStream()); 
    Mock<ViewContext> mockViewContext = new Mock<ViewContext>(
     new ControllerContext(
      new Mock<HttpContextBase>().Object, 
      new RouteData(), 
      new Mock<ControllerBase>().Object 
     ), 
     new Mock<IView>().Object, 
     vd, 
     new TempDataDictionary(), 
     textWriter 
    ); 
    mockViewContext.Setup(vc => vc.Writer).Returns(textWriter); 

    Mock<IViewDataContainer> mockDataContainer = new Mock<IViewDataContainer>(); 
    mockDataContainer.Setup(c => c.ViewData).Returns(vd); 

    return new HtmlHelper(mockViewContext.Object, mockDataContainer.Object); 
} 
+0

一定有什麼缺。我有一個'System.NullReferenceException'。 「你調用的對象是空的」。任何想法? – Blaise 2015-05-14 17:04:50

+0

您可能需要確保在模擬對象上將「CallBase」設置爲true,以便正確設置屬性。你不需要做'mockViewContext.Setup(vc => vc.Writer).Returns(textWriter);'也可以。 – 2015-12-21 14:03:19