Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何使用RenderPartialViewToString为返回JsonResult的方法编写单元测试?_Unit Testing_Model View Controller_Rhino Mocks_Mvccontrib - Fatal编程技术网

Unit testing 如何使用RenderPartialViewToString为返回JsonResult的方法编写单元测试?

Unit testing 如何使用RenderPartialViewToString为返回JsonResult的方法编写单元测试?,unit-testing,model-view-controller,rhino-mocks,mvccontrib,Unit Testing,Model View Controller,Rhino Mocks,Mvccontrib,如果您查看此链接中的示例: 如何为JsonAdd方法编写单元测试?我自己的代码中也有类似的情况,但调用时RenderPartialViewToString错误: ViewEngineResult viewResult=ViewEngines.Engines.FindPartialView 我尝试了不同的方法来截短那个电话,但都没有用。谢谢你的帮助。谢谢。因为viewEnginges是一个静态类,所以不能用rhinomock来模拟它。我认为最好的办法是创建“局部视图渲染器”界面。接口是可模拟的,

如果您查看此链接中的示例:

如何为JsonAdd方法编写单元测试?我自己的代码中也有类似的情况,但调用时RenderPartialViewToString错误:

ViewEngineResult viewResult=ViewEngines.Engines.FindPartialView


我尝试了不同的方法来截短那个电话,但都没有用。谢谢你的帮助。谢谢。

因为viewEnginges是一个静态类,所以不能用rhinomock来模拟它。我认为最好的办法是创建“局部视图渲染器”界面。接口是可模拟的,因此您可以消除渲染视图的复杂性。下面是一些快速生成的伪代码

首先,定义局部视图渲染器界面:

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,但在生产期间使用基类1。我们可以通过使用一对构造函数来实现这一点:

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

我在使用RenderPartialView进行单元测试时遇到了很多麻烦。 我成功地做了两件事。 我不得不模拟视图引擎和控制器上下文

代码如下:

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);
    }
以下是我的资料来源: 查看引擎模拟:

控制器上下文模拟:


希望这能有所帮助。

我正在将依赖项与接口隔离,但还没有完全理解多重构造函数的概念。很好…谢谢你,帕特里克!做得很好。适用于所有与RouteConfigurator有问题的人。RegisterRoutes默认位于Global.asax.cs中,它是MVCAPApplication(默认)的一部分。感谢这段代码,它对我帮助很大。
PointCollecteLivraisonController controller = new PointCollecteLivraisonController();
SetContext(ref controller);