gpt4 book ai didi

c# - 模拟 Controller 以测试区域内的 ViewEngine - nullreference 和 RouteData

转载 作者:太空宇宙 更新时间:2023-11-03 12:24:35 26 4
gpt4 key购买 nike

我的 MVC 站点中有一个 Area。该区域具有典型的 Controller /模型/ View 设置。

作为 Controller ,我有以下代码:

public class DocumentCreatorController : Controller
{
// GET: Templates/DocumentCreator
public ActionResult OfferTemplate(BaseDocumentViewModel data)
{
return this.Pdf(nameof(OfferTemplate), data, "File.pdf");
}
}

this.Pdf 方法做了一些事情,但有趣的是它归结为 ViewEngine 调用:

var viewResult = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName);

在这里,我使用 ControllerContextPartialViewName 调用了 FindPartialView。我的 PartialViewName 来自 Controller 操作 OfferTemplatenameof(OfferTemplate)。我认为 controllercontext 是我的挑战。

我的挑战:

当我想在单元测试中设置它时(使用 Moq),我有以下基于页面的代码,例如 Mocking The RouteData Class in System.Web.Routing for MVC applicationsMocking Asp.net-mvc Controller Context :

[TestMethod]
public void OfferTemplate()
{
var ctr = SetupControllerWithContext();

}

private static DocumentCreatorController SetupControllerWithContext()
{
var routeData = new RouteData();
routeData.Values.Add("controller", "DocumentCreatorController");
routeData.Values.Add("action", "OfferTemplate");


var request = new Mock<HttpRequestBase>();
request.Expect(r => r.HttpMethod).Returns("GET");
var mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(request.Object);
var controllerContext = new ControllerContext(mockHttpContext.Object
, routeData, new Mock<ControllerBase>().Object);

DocumentCreatorController ctr = new DocumentCreatorController();
ctr.ControllerContext = controllerContext;
return ctr;
}

这给出了以下错误:

Eesy.Websites.Api.Tests.Controllers.DocumentCreatorControllerTest.OfferTemplate threw exception: System.NullReferenceException: Object reference not set to an instance of an object.

这个我不明白。

我的文件夹设置:

enter image description here

调用 FindPartialView 时在 ControllerContext 上调试图像:

enter image description here

有人有想法吗?是不是我RouteData设置错了?

最佳答案

您正在尝试模拟和测试框架代码。将该功能抽象为您控制的代码,以便您可以在需要时进行隔离测试。

目前, Action 和扩展 Controller 与外部第 3 方依赖项紧密耦合。如果目标是单独测试 Controller 操作流程,那么建议抽象出第 3 方 PDF 生成,以便可以模拟它以实现更容易的可测试性。

public interface IDocumentService {
ActionResult ToPdf(Controller arg1, string arg2, object arg3, string arg4);
}

Controller 将通过构造函数注入(inject)显式依赖于此抽象。

public class DocumentCreatorController : Controller {
private readonly IDocumentService render;

DocumentCreatorController(IDocumentService render) {
this.render = render;
}

// GET: Templates/DocumentCreator
public ActionResult OfferTemplate(BaseDocumentViewModel data) {
return render.ToPdf(this, nameof(OfferTemplate), data, "File.pdf");
}
}

所以现在要测试 Controller 的 pdf 生成过程,您只需要模拟您的抽象。

[TestMethod]
public void OfferTemplate() {
//Arrange
var serviceMock = new Mock<IDocumentService>();
//...setup mock for use case

var controller = new DocumentCreatorController(serviceMock.Object);
var data = new BaseDocumentViewModel {
//...
};

//Act
var actual = controller.OfferTemplate(data);

//Assert
//...assert behavior
}

服务的实际实现将封装实际功能,并将与抽象一起注册到依赖注入(inject)容器。

要测试实际生成,您需要进行集成测试,这是另一个主题。

关于c# - 模拟 Controller 以测试区域内的 ViewEngine - nullreference 和 RouteData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45691855/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com