This is a migrated thread and some comments may be shown as answers.

displaymode is null when mocking ControllerContext

6 Answers 499 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Lee Saunders
Top achievements
Rank 1
Lee Saunders asked on 22 Apr 2013, 09:39 PM
Hello,

I'm trying to mock a controller.ControllerContext and everything is working until the system tries to GetDisplayMode on the context.  Since it is null, it blows up.

Here are two functions, the first creates the controller and the second uses the controller and blows up.

Any help would be appreciated!

Lee
private static LogonController CreateLogonController()
        {
            var controller = new LogonController();
            var response = Mock.Create<HttpResponseBase>();
            var httpContext = Mock.Create<HttpContextBase>();
            var routeData = new RouteData();
            var request = Mock.Create<HttpRequestBase>();
            var cookies = new HttpCookieCollection();
            var context = new ControllerContext(httpContext, routeData, Mock.Create<ControllerBase>());
            var browser = Mock.Create<HttpBrowserCapabilitiesBase>();
 
            response.Output = new StringWriter();
 
            Mock.Arrange(() => browser.IsMobileDevice).Returns(false);
 
            Mock.Arrange(() => request.Cookies).Returns(cookies);
            Mock.Arrange(() => request.ValidateInput());
            Mock.Arrange(() => request.UserAgent).Returns("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
            Mock.Arrange(() => request.Browser).Returns(browser);
 
            Mock.Arrange(() => response.Cookies).Returns(cookies);
 
            Mock.Arrange(() => httpContext.Request).Returns(request);
            Mock.Arrange(() => httpContext.Response).Returns(response);
 
            routeData.Values.Add("controller", "LogonController");
            routeData.Values.Add("action", "Index");
            controller.ControllerContext = context;
 
            return controller;
        }


And here I am trying to use it to generate  the output of a view:

public static class ApiExtensionMethods
{
    public static string Render(this ViewResult result, Controller controller)
    {
        controller.ViewData.Model = result.Model;
        try
        {
            using (var sw = new StringWriter())
            {
                var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, result.ViewName);
                var 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();
        }
    }
}

6 Answers, 1 is accepted

Sort by
0
Kaloyan
Telerik team
answered on 24 Apr 2013, 11:14 AM
Hello Lee,

Thank you for the sample code.

However, I was not able to identify the issue. Is it possible to send us a compiling project containing the JustMock tests and the SUT (System Under Test). This will let us investigate the matter and accordingly provide s solution faster.

If this is not doable, please give more information about the exception you are experiencing and what invokes it.

Thank you for the understanding.

Greetings,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Lee Saunders
Top achievements
Rank 1
answered on 24 Apr 2013, 05:34 PM
Hello!

No problem.  Here is a link to a zip file that contains the smallest possible MVC4 project.

It contains just a single controller (HOME) with a single action (INDEX) and a test project that tries to render the view to html.

the extension method that renders the view works great inside of the contoller when called by a browser, but by a test with a mocked up controller, not so much.

To see others struggling with this change in MVC4 from MVC3, see:
http://stackoverflow.com/questions/13348169/mvc-4-mocking-httpcontext-how-to-mock-displaymodeprovider

Link to my example:
http://www.leesaunders.net/examples/renderviewexample/renderviewexample.zip

Thanks again,
Lee
0
Kaloyan
Telerik team
answered on 29 Apr 2013, 11:21 AM
Hello Lee,

Thank you for the links.

To avoid this exception you will need to have the Items property in HttpContextBase mocked as well. I added the following line in the CreateHomeController class and it did the job:
Mock.Arrange(() => httpContext.Items).Returns(Mock.Create<IDictionary>());
However, for the whole test to pass, you will need to further arrange some other dependencies.

I hope this helps.

Kind regards,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Lee Saunders
Top achievements
Rank 1
answered on 01 May 2013, 09:31 PM
Hello Kaloyan,

You are right, that got me past the exception.  You are also correct that it just walked me into another exception.  Seems like either I need a lot more help getting this to "Green", or I need to look at other alternatives on how to get my "rendered" "view".

Thanks.
Lee
0
Kaloyan
Telerik team
answered on 07 May 2013, 12:02 PM
Hello Lee,

Sorry for the late reply.

However, I will further investigate the issue and will try to provide possible solution(s). Please, let me contact you once again in the very near future.

I hope this helps.

All the best,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Kaloyan
Telerik team
answered on 11 Nov 2013, 01:46 PM
Hello Lee,

With the release of JustMock 2013 Q3, we introduced the RecursiveLoose mocks. With them, I was able to find solution to the matter.

I added several more arrangements inside your CreateHomeController() class, as follows (the new lines are marked with yellow):
private static HomeController CreateHomeController()
{
    var browser = Mock.Create<HttpBrowserCapabilitiesBase>();
    var response = Mock.Create<HttpResponseBase>();
    var httpContext = Mock.Create<HttpContextBase>();
    var request = Mock.Create<HttpRequestBase>();
    var engine = Mock.Create<IViewEngine>(); // Mocking IViewEngine
    var view = Mock.Create<IView>(); // Mocking IView
    var cookies = new HttpCookieCollection();
    var items = new ListDictionary();
 
    // Creating a ViewEngineResult, containing our mocks.
    var viewEngineResult = new ViewEngineResult(view, engine);
    // Arranging the FindPartialView to return our predefined viewEngineResult.
    Mock.Arrange(() => engine.FindPartialView(null, null, false)).IgnoreArguments().Returns(viewEngineResult);
    // Arranging the Render method of the IView mock to write inside the StringWriter.
    // We will assert on this later in the test.
    Mock.Arrange(() => view.Render(Arg.IsAny<ViewContext>(), Arg.IsAny<StringWriter>()))
        .DoInstead((ViewContext context1, StringWriter sw) => sw.Write("<h2>Index</h2>"));
    // Adding the mocked IViewEngine to the ViewEngines collection.
    ViewEngines.Engines.Add(engine);
 
    var controller = new HomeController();
    var routeData = new RouteData();
    var context = new ControllerContext(httpContext, routeData, Mock.Create<ControllerBase>());
 
    response.Output = new StringWriter();
 
    Mock.Arrange(() => browser.IsMobileDevice).Returns(false);
 
    Mock.Arrange(() => request.Cookies).Returns(cookies);
    Mock.Arrange(() => request.ValidateInput()).DoNothing();
    Mock.Arrange(() => request.UserAgent)
        .Returns(
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
    Mock.Arrange(() => request.Browser).Returns(browser);
 
    Mock.Arrange(() => response.Cookies).Returns(cookies);
 
    Mock.Arrange(() => httpContext.Items).Returns(items);
     
    Mock.Arrange(() => httpContext.Request).Returns(request);
    Mock.Arrange(() => httpContext.Response).Returns(response);
 
    routeData.Values.Add("controller", "HomeController");
    routeData.Values.Add("action", "Index");
    controller.ControllerContext = context;
 
    return controller;
}
With the above changes, your test works as expected.

As I understand the answer comes late, I deeply apologize for all the inconveniences caused and hope you find it helpful.

Regards,
Kaloyan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Tags
General Discussions
Asked by
Lee Saunders
Top achievements
Rank 1
Answers by
Kaloyan
Telerik team
Lee Saunders
Top achievements
Rank 1
Share this question
or