Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MissingMethodException thrown when trying to mock HtmlHelper with Moq

When attempting to follow the article on mocking the htmlhelper with Moq I ran in to the following problem. The exception is thrown on creation of the htmlhelper. I am only guessing that castle windsor is being used (by seeing the error message).

The exception:

MissingMethodException occurred

Constructor on type 'Castle.Proxies.ViewContextProxy' not found.

Stack Trace:

at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

The Code:

    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());

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

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

I am using ASP MVC 2, Moq 4.0 beta 3, VS2010, using the IDE's testing framework.

How do I resolve the issue and return an instance of HtmlHelper?

like image 927
MedicineMan Avatar asked Aug 10 '10 03:08

MedicineMan


2 Answers

You get MissingMethodException when MOQ can't match parameters to Mock<>() to the parameters on the mocked class's constructor.

Looking at ViewContext explains why. There is only one constructor overload and it is this:

 public ViewContext(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer);

This setup(includes missing TextWriter mock) should work:

   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 Mock<TextWriter>().Object);

PS MOQ uses Castle Dynamic Proxy to create mocked classes at runtime, hence the name Castle in the exception that you are seeing. Castle Windsor uses Dynamic Proxy project, but they are quite distinct projects.

like image 98
Igor Zevaka Avatar answered Nov 08 '22 07:11

Igor Zevaka


I've reproduced your issue with the code from my blog post. The following updated method works for me:

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 Mock<TextWriter>().Object);

    mockViewContext.Setup(vc => vc.ViewData).Returns(vd);

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

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

I have posted an update on my blog as well.

like image 36
Håvard S Avatar answered Nov 08 '22 07:11

Håvard S