2010-03-22 105 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