gpt4 book ai didi

c# - 如何在 ControllerContext 中模拟 DisplayMode 以进行单元测试 c#

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

我想在我的 Controller 中测试一个 Action ,该 Action 使用 controllerContext 作为参数来生成基于第 3 部分库“Rotativa”的 pdf 文档。
这是 Action (功能)的实现:

public ActionResult DetailsPrint(int? id)
{
var a = new ViewAsPdf();
a.ViewName = "../Ops/_2A1/Details";
a.Model =UnitOfWork._2A1s.Get(id.Value);
var pdfBytes = a.BuildPdf(ControllerContext);

// return ActionResult
MemoryStream ms = new MemoryStream(pdfBytes);
return new FileStreamResult(ms, "application/pdf");

}

下面是我试图让单元测试工作的方法:

  • 构造函数

    public _2A1ControllerTest()
    {
    _mockRepository = new Mock<I2A1Repository>();
    var mockUoW = new Mock<IUnitOfWork>();
    _mockHttpContext = new Mock<HttpContextBase>();
    _mockRequest = new Mock<HttpRequestBase>();
    _mockDisplayModeContext = new Mock<IDisplayMode>();
    mockUoW.SetupGet(u => u._2A1s).Returns(_mockRepository.Object);
    _mockHttpContext.SetupGet(x => x.Request).Returns(_mockRequest.Object);
    _controller = new _2A1Controller(mockUoW.Object);
    _controller.MockCurrentUser("test.admin");
    _controller.ControllerContext = new ControllerContext(_mockHttpContext.Object, new System.Web.Routing.RouteData(), _controller);
    }
  • 测试函数

    [TestMethod]
    public void DetailsPrint_shouldPrint()
    {
    var result = _controller.DetailsPrint(1) as ActionResult;
    result.Should().BeOfType<ActionResult>();
    }

    当我执行测试时,出现以下错误: enter image description here

Test Name: DetailsPrint_shouldPrint Test FullName: OPSReviewTest._2A1ControllerTest.DetailsPrint_shouldPrint Test Source: C:\inetpub\wwwroot\OpsReview\OPSReviewTest\Controllers\Api_2A1ControllerTest.cs : line 46 Test Outcome: Failed Test Duration: 0:04:39,3039007 Result StackTrace:
at System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase context) at System.Web.Mvc.ControllerContext.get_DisplayMode() Result Message: Test method OPSReviewTest._2A1ControllerTest.DetailsPrint_shouldPrint threw exception: System.NullReferenceException: Object reference not set to an instance of an object.

任何帮助或建议,谢谢。

最佳答案

您正在尝试对您不拥有的代码进行单元测试? (耻辱,[钟声],耻辱...)

如果目标是单独测试 Controller 操作流,那么建议抽象出第 3 方 PDF 生成,以便可以模拟它以实现更容易的可测试性。

public interface IViewAsPdfWrapper {
string ViewName { get; set; }
object Model { get; set; }
byte[] BuildPdf(ControllerContext context);
}

public class ViewAsPdfWrapper : IViewAsPdfWrapper {
private readonly ViewAsPdf view;
public ViewAsPdfWrapper() {
view = new ViewAsPdf();
}
public string ViewName { get; set; }
public object Model { get; set; }
public byte[] BuildPdf(ControllerContext context) {
view.ViewName = ViewName;
view.Model = Model;
return view.BuildPdf(context);
}
}

现在可以将抽象注入(inject)到 Controller 中,以便根据需要在每个请求操作中使用。

public class _2A1Controller : Controller {
private readonly IUnitOfWork UnitOfWork;
private readonly IViewAsPdfWrapper viewAsPdf;

public _2A1Controller(IUnitOfWork uow, IViewAsPdfWrapper viewAsPdf) {
this.UnitOfWork = uow;
this.viewAsPdf = viewAsPdf;
}

public ActionResult DetailsPrint(int? id) {
var a = viewAsPdf;
a.ViewName = "../Ops/_2A1/Details";
a.Model = UnitOfWork._2A1s.Get(id.Value);
var pdfBytes = a.BuildPdf(ControllerContext);

// return ActionResult
MemoryStream ms = new MemoryStream(pdfBytes);
return new FileStreamResult(ms, "application/pdf");
}

}

现在单元测试可以安全地模拟第 3 方功能

public _2A1ControllerTest() {    
_mockRepository = new Mock<I2A1Repository>();
var mockUoW = new Mock<IUnitOfWork>();
mockUoW.SetupGet(u => u._2A1s).Returns(_mockRepository.Object);

var mockViewAsPdf = new Mock<IViewAsPdfWrapper>();
mockViewAsPdf.Setup(m => m.BuildPdf(It.IsAny<ControllerContext>()))
.Returns(() => new byte[0]);

_mockRequest = new Mock<HttpRequestBase>();
_mockHttpContext = new Mock<HttpContextBase>();
_mockHttpContext.SetupGet(x => x.Request).Returns(_mockRequest.Object);

_controller = new _2A1Controller(mockUoW.Object, mockViewAsPdf.Object);
_controller.MockCurrentUser("test.admin");
_controller.ControllerContext = new ControllerContext(_mockHttpContext.Object, new System.Web.Routing.RouteData(), _controller);

}

假设使用 FluentAssertions,测试方法应该是这样的(双关语:))

[TestMethod]
public void DetailsPrint_shouldPrint() {
var result = _controller.DetailsPrint(1) as ActionResult;
result.Should()
.NotBeNull()
.And
.BeAssignableTo<ActionResult>();
}

最后,不要忘记在生产中使用 DI 容器注册接口(interface)及其实现。

关于c# - 如何在 ControllerContext 中模拟 DisplayMode 以进行单元测试 c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40789343/

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