Как написать модульный тест для метода, возвращающего JsonResult с RenderPartialViewToString? - PullRequest
3 голосов
/ 11 августа 2010

Если вы посмотрите на пример по этой ссылке:

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

Как написать модульный тест для метода JsonAdd?У меня похожая ситуация в моем собственном коде, но ошибки RenderPartialViewToString при вызове:

ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView

Я пробовал разные способы попытаться заблокировать этот вызовбезрезультатно.Любая помощь приветствуется.Благодаря.

Ответы [ 2 ]

6 голосов
/ 26 июля 2012

У меня было много проблем, чтобы заставить модульный тест работать с RenderPartialViewToString. Мне удалось сделать 2 вещи. Мне пришлось издеваться над двигателем представления и контекстом контроллера.

Вот код:

public ViewEngineResult SetupViewContent(string viewName, string viewHtmlContent)
    {
        var mockedViewEngine = new Mock<IViewEngine>();
        var resultView = new Mock<IView>();

        resultView.Setup(x => x.Render(It.IsAny<ViewContext>(), It.IsAny<TextWriter>()))
            .Callback<ViewContext, TextWriter>((v, t) =>
            {
                t.Write(viewHtmlContent);
            });

        var viewEngineResult = new ViewEngineResult(resultView.Object, mockedViewEngine.Object);
        mockedViewEngine.Setup(x => x.FindPartialView(It.IsAny<ControllerContext>(), viewName, It.IsAny<bool>()))
            .Returns<ControllerContext, string, bool>((controller, view, useCache) =>
            {
                return viewEngineResult;
            });

        mockedViewEngine.Setup(x => x.FindView(It.IsAny<ControllerContext>(), viewName, It.IsAny<string>(), It.IsAny<bool>()))
            .Returns<ControllerContext, string, string, bool>((controller, view, masterName, useCache) =>
            {
                return viewEngineResult;
            });

        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(mockedViewEngine.Object);
        return viewEngineResult;
    }

    public void SetContext(ref PointCollecteLivraisonController controller)
    {
        SetupViewContent("MyViewName", "TheViewContent");

        var httpContextBase = new Mock<HttpContextBase>();
        var httpRequestBase = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var routes = new RouteCollection();
        RouteConfigurator.RegisterRoutes(routes);
        var routeData = new RouteData();
        routeData.Values.Add("controller", "PointCollecteLivraison");
        routeData.Values.Add("action", "RechercheJson");

        httpContextBase.Setup(x => x.Response).Returns(response.Object);
        httpContextBase.Setup(x => x.Request).Returns(httpRequestBase.Object);
        httpContextBase.Setup(x => x.Session).Returns(session.Object);
        session.Setup(x => x["somesessionkey"]).Returns("value");
        httpRequestBase.Setup(x => x.Form).Returns(new NameValueCollection());
        controller.ControllerContext = new ControllerContext(httpContextBase.Object, routeData, controller);
        controller.Url = new UrlHelper(new RequestContext(controller.HttpContext, routeData), routes);
    }

И вот как я все это использую:

PointCollecteLivraisonController controller = new PointCollecteLivraisonController();
SetContext(ref controller);

Вот мои источники: Просмотр макета двигателя: http://thoai -nguyen.blogspot.fr / 2011/04 / test-mock-mvc-view-engine.html

Контроллинг контекста контроллера: ASP.NET MVC - Модульное тестирование RenderPartialViewToString () с использованием инфраструктуры Moq?

Надеюсь, эта помощь.

2 голосов
/ 12 августа 2010

Поскольку ViewEninges является статическим классом, вы не можете смоделировать его с помощью RhinoMocks. Я думаю, что вам лучше всего создать интерфейс «частичного представления изображений». Интерфейс подделок, так что вы сможете устранить сложность рендеринга вида. Вот несколько быстрых псевдокодов, собранных вместе.

Сначала определите интерфейс средства частичного представления:

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

Затем измените базовый класс RenderPartialViewToString на реализацию IRenderPartialView.Render:

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

Теперь нам нужно изменить конструкторы вашего контроллера, чтобы мы могли внедрить IRenderPartialView во время тестирования, но использовать базовый класс один во время производства. Мы можем сделать это с помощью пары конструкторов:

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;
        }
}

Теперь JsonAdd может вызвать средство частичного отображения:

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

Итак, во время тестирования вы смоделируете IRenderPartialView и отправите его конструктору, который принимает IRenderPartialView. Во время работы, когда ASP.NET MVC вызывает ваш конструктор по умолчанию, он будет использовать контроллер в качестве средства визуализации (реализация которого IRenderPartialView.Render внутри базового класса).

...