Как смоделировать DisplayMode в ControllerContext для модульного теста C#
Я хочу протестировать действие в моем контроллере, которое использует controllerContext в качестве параметра для генерации PDF-документа на основе библиотеки 3-й части "Rotativa".
Вот реализация действия (функции):
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>(); }
Имя теста: DetailsPrint_shouldPrint Тест Полное имя: OPSReviewTest._2A1ControllerTest.DetailsPrint_shouldPrint Источник теста: C:\inetpub\wwwroot\OpsReview\OPSReviewTest\Controllers\Api_2A1ControllerTest.cs: Тест 04: тестирование: 0: Строка 46:
в System.Web.WebPages.DisplayModeProvider.GetDisplayMode(контекст HttpContextBase) в System.Web.Mvc.ControllerContext.get_DisplayMode() Сообщение о результате: тестовый метод OPSReviewTest._2A1ControllerTest.DetailsPrint.Exception экземпляр класса: исключение_принятия объекта.
Любая помощь или предложение, спасибо.
2 ответа
Вы пытаетесь выполнить юнит-код, который вам не принадлежит? (Позор, [Звонок звонит], позор...)
Если цель состояла в том, чтобы протестировать поток действий контроллера изолированно, то рекомендуется абстрагировать стороннее поколение 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);
}
}
Теперь абстракция может быть введена в контроллер для использования при каждом действии запроса.
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");
}
}
И теперь юнит тест может смело издеваться над сторонней функциональностью
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, метод теста должен выглядеть следующим образом (Pun предназначен:))
[TestMethod]
public void DetailsPrint_shouldPrint() {
var result = _controller.DetailsPrint(1) as ActionResult;
result.Should()
.NotBeNull()
.And
.BeAssignableTo<ActionResult>();
}
Наконец, не забудьте зарегистрировать интерфейс и его реализацию в вашем DI-контейнере.
Вы забыли назначить DsiplayMode
Недвижимость в ControllerContext
Добавь это:
_controller.ControllerContext.DisplayMode=_mockDisplayModeContext.Object;