如果您查看此链接中的示例:
http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/
如何为JsonAdd方法编写单元测试?我在自己的代码中有类似的情况,但调用时出现RenderPartialViewToString错误:
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView
我尝试了不同的尝试存根的方法,但无效。任何帮助赞赏。感谢。
答案 0 :(得分:6)
使用RenderPartialViewToString进行单元测试时遇到了很多麻烦。 我成功做了两件事。 我不得不模拟视图引擎和控制器上下文。
这里是代码:
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 - Unit testing RenderPartialViewToString() with Moq framework?
希望得到这个帮助。
答案 1 :(得分:2)
由于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,但在生产期间使用基类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
的实现)。