2010-10-01 10 views
6

Zrobiłem wyszukiwanie w SO i wygląda na to, że to pytanie jest często zadawane. Udało mi się sprawić, że mocky działają, a ja też mogę wykonywać OnActionExecuted() bez żadnych problemów. Oto mój test jednostkowy. Skomentowane linie to te, które zawiodły i jestem pewien, że nie kpię z właściwego typu.Jednostki testujące filtry akcji - jak kpić z ViewResult

 //Arrange 
     //var viewResult = new ViewResult(); 
     var filterContextMock = new Mock<ActionExecutedContext>(); 
     var routeData = new RouteData(); 
     var httpContextMock = new Mock<HttpContextBase>(); 

     routeData.Values["data"] = "Mock data"; 
     var requestContext = new RequestContext(httpContextMock.Object, routeData); 

     var controller = new FakeController(); 
     controller.ControllerContext = new ControllerContext(requestContext, controller); 

     filterContextMock.Setup(f => f.RouteData).Returns(routeData); 
     filterContextMock.Setup(f => f.Controller).Returns(controller); 
     //filterContextMock.Setup(f => f.Result).Returns(viewResult); 

     //Act 
     var wrapFilterAttribute = new WrapFilterAttribute(); 
     wrapFilterAttribute.OnActionExecuted(filterContextMock.Object); 

Oto mój filtr działania.

public class WrapFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var view = (ViewResultBase)filterContext.Result; 

     if (view != null) 
     { 
      BaseViewModel viewModel = (BaseViewModel)view.ViewData.Model ?? new BaseViewModel(); 
      viewModel.Wrap = new WrapperFactory().GetWrap(); 
     } 

     base.OnActionExecuted(filterContext); 
    } 
} 

Kwestia, przed którą stoję, to filterContext.Result zawsze pojawia się jako EmptyResult. Chciałbym zamiast tego wepchnąć uwodniony ViewResult. Jakieś pomysły, jak mogę to osiągnąć?

Wielkie dzięki!

Odpowiedz

9

Najpierw zacznijmy od mocowania filtra działania jak obecnie kod wygląda źle i te odlewy może przynieść Ci głowy:

public class WrapFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var view = filterContext.Result as ViewResultBase; 
     if (view != null) 
     { 
      // the controller action returned a ViewResultBase 
      var viewModel = view.ViewData.Model as BaseViewModel; 
      if (viewModel != null) 
      { 
       // the model passed to the view was derived from 
       // BaseViewModel so we can safely update the Wrap 
       // property 
       viewModel.Wrap = new WrapperFactory().GetWrap(); 
      } 
     } 
     base.OnActionExecuted(filterContext); 
    } 
} 

a test jednostka:

// arrange 
var sut = new WrapFilterAttribute(); 
var filterContextMock = new Mock<ActionExecutedContext>(); 
var viewResultMock = new Mock<ViewResultBase>(); 
filterContextMock.Object.Result = viewResultMock.Object; 
var viewModel = new BaseViewModel(); 
viewResultMock.Object.ViewData.Model = viewModel; 

// act 
sut.OnActionExecuted(filterContextMock.Object); 

// assert 
// TODO: assert something on the viewModel.Wrap property like 
// for example that it has been initialized 

uwaga: filtr akcja ma silną zależność od klasy WrapperFactory. To nie jest dobre. Dalszą poprawą byłoby streszczenie funkcji w interfejsie, który zostałby wprowadzony do konstruktora filtru akcji. Pozwoliłoby to na dalsze oddzielenie obaw między różnymi warstwami aplikacji.

+0

Dzięki za refaktoryzację mojego brzydkiego kodu Darin. To działało dla mnie. Jeszcze raz dziękuję :) – Praveen

+0

Twój komentarz na temat wstrzykiwania WrapperFactory do konstruktora filtru akcji sprawia, że ​​jestem ciekawy. Jak można przesłać instancję WrapperFactory poprzez dekorację WrapFilterAttribute? AFAIK, atrybuty wymagają wartości czasu kompilacji (stałe itp.). – Praveen

+1

@Praveen, oto przykład, jak uzyskać [konstruktor wtrysku z filtrami akcji] (http://iridescence.no/post/Constructor-Injection-for-ASPNET-MVC-Action-Filters.aspx). To trochę hacky, ale to jedyny sposób na tę chwilę. Zostało to ulepszone w ASP.NET MVC 3. –

Powiązane problemy