views:

75

answers:

2

If you look at the example at this link:

http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/

How would one write a unit test for the JsonAdd method? I have a similar situation in my own code, but the RenderPartialViewToString errors when calling:

ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView

I've tried different ways of trying to stub that call to no avail. Any help appreciated. Thanks.

A: 

Since ViewEninges is a static class, you can't mock it with RhinoMocks. I think your best bet is to create a "partial view renderer" interface. An interface is mockable so you'll be able to stub out the complexity of rendering the view. Here's some quick pseudo-code thrown together.

First, define the partial view renderer interface:

public interface IRenderPartialView
{
    string Render(string viewName, object model);
}

Then, change your base class' RenderPartialViewToString to be the implementation of IRenderPartialView.Render:

public abstract class BaseController : Controller, IRenderPartialView
{
...
    public string Render(string viewName, object model)
    {
        // same code as RenderPartialViewToString
    }
}

Now we need to change your controller constructors so we can inject an IRenderPartialView during testing -- but use the base class one during production. We can accomplish this by using a pair of constructors:

public class YourController : BaseController
{
        private IRenderPartialView partialRenderer;

        public YourController()
        {
            SetRenderer(this);
        }

        public YourController(IRenderPartialView partialRenderer)
        {
            SetRenderer(partialRenderer);
        }

        private void SetRenderer(IRenderPartialView partialRenderer)
        {
            this.partialRenderer = this;
        }
}

Now, JsonAdd can call the partial view renderer:

public JsonResult JsonAdd(AddPersonViewModel AddPersonModel)
{
    ...
    return Json(new
    {
        Success = true,
        Message = "The person has been added!",
        PartialViewHtml = partialRenderer.Render("PersonList", new PersonListViewModel {PersonList = _personList})
    });
}

So, during testing, you'll mock out an IRenderPartialView and send that to the constructor that accepts an IRenderPartialView. During production, when ASP.NET MVC calls your default constructor, it will use the controller as the renderer (which has the implementation of IRenderPartialView.Render inside the base class).

Patrick Steele
I was in the process of isolating the dependency to an interface, but had not quite gotten to the multiple constructor idea. Works great...thanks Patrick!
Shawn
A: 

I'm having a similar problem, whenever I run unit test, I got the "Object reference not set to an instance of an object." error on ControllerContext.

I'm using Moq to mockup the controller, here's the code

private ProgramsController GetController()
{
var mockHttpContext = new Mock<ControllerContext>();
mockHttpContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("test");
mockHttpContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
// Mock Repositories
var mockOrganizationRepository = new MockOrganizationRepository(MockData.MockOrganizationsData());
var mockIRenderPartial = new BaseController();
var controller = new ProgramsController(mockOrganizationRepository, mockIRenderPartial);
controller.ControllerContext = mockHttpContext.Object;
return controller;
}

This returns a proxy controller, and maybe it's the reason why I got that error. Any idea how to unit testing this?

Thank you very much.

Saxman