2016-11-24 8 views
2

Я хочу проверить действие в контроллере, использующее controlContext в качестве параметра для создания pdf-документа на основе библиотеки 3-й части «Rotativa».
Вот реализация действия (функции):Как издеваться над DisplayMode в ControllerContext для модульного тестирования C#

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"); 

} 

А вот как я пытаюсь получить модульное тестирование работы:

  • Constructor

    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>(); 
    } 
    

    Когда я выполнить тест я получаю follwing ошибку ниже: enter image description here

Имя теста: DetailsPrint_shouldPrint Тест FullName: OPSReviewTest._2A1ControllerTest.DetailsPrint_shouldPrint Test Источник: C: \ Inetpub \ Wwwroot \ OpsReview \ OPSReviewTest \ Контроллеры \ Api_2A1ControllerTest.cs: линия 46 Тест Результат: Failed Test Продолжительность: 0: 04: 39,3039007 Результат StackTrace:
в System.Web.WebPages.Display ModeProvider.GetDisplayMode (HttpContextBase контекст) в System.Web.Mvc.ControllerContext.get_DisplayMode() Результат Сообщение: Метод испытания OPSReviewTest._2A1ControllerTest.DetailsPrint_shouldPrint бросили исключение: System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта ,

Любая помощь или предложение, спасибо.

+0

Что именно вы пытаетесь протестировать в методе? – Nkosi

ответ

1

Вы пытаетесь модульного тестирования кода, который вы не владеете? (Позор, [Колокол], позор ...)

Если цель состояла в том, чтобы протестировать поток действий контроллера изолированно, тогда рекомендуется абстрагироваться от третьего поколения 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"); 
    } 

} 

А теперь тест устройство может безопасно издеваться 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 в процессе производства.

+0

Прежде всего, спасибо, что помогли мне, спасите меня много времени и поисков, я действительно это утверждаю. Для вас вопрос, это мой собственный код, и мой первый опыт работы с mocks и имитация библиотеки 3-й части. Вы - ученый в этом. –

+1

Когда я сказал собственный код, я имел в виду стороннюю библиотеку. Это поговорка и означала как шутка :). провайдер сторонней библиотеки должен был протестировать свой код перед его выпуском. Поэтому попытка проверить это пустая трата времени. обернув его в абстракцию, которой вы владеете, у вас есть контроль над возможностью издеваться над ней и протестировать с большей гибкостью. – Nkosi

+0

Ну ладно, спасибо за все эти советы и за ваше время. –

0

Вы забыли присвоить DsiplayMode свойства в ControllerContext добавить следующее:

_controller.ControllerContext.DisplayMode=_mockDisplayModeContext.Object; 
+0

Спасибо @esiprogrammer за ответ, но это не сработало, –

+0

@ayyoub Что вы имеете в виду, это не сработало. У все еще есть одно и то же исключение в одной строке? – esiprogrammer

+0

Да, у меня все же есть то же исключение, я провел 4 часа с ним вчера безрезультатно, затем я положил его в stackoverflow, надеясь, что у кого-то была такая же проблема раньше. Спасибо за вашу интерактивность. –