2010-10-01 30 views
6

SO üzerinde bir arama yaptım ve bu soruyu oldukça sık sorulana benziyor. Sahte çalışmayı başarabildim ve ayrıca herhangi bir sorun yaşamadan OnActionExecuted() yöntemini de çalıştırabiliyorum. İşte Birim Testim. Yorumlanan satırlar başarısız olanlardır ve eminim ki doğru türde alay etmiyorum.Birim Test Etme İşlemi Filtreleri - Nasıl Yapılır? Hata Düzeltme

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

İşte İşlem Filtrem.

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

Buraya karşı karşıya olduğum sorun filterContext.Result her zaman EmptyResult olarak geliyor. Bunun yerine hidratlı bir ViewResult itmek istiyorum. Bunu nasıl başarabilirim?

Çok teşekkürler!

cevap

9

İlk önce şu anda kod kötü görünüyor gibi eylem filtreyi düzelterek başlayalım ve bu dökümler baş ağrısı getirebilir:

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

Ve birim testi:

// 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 

Not: eyleminizle filtresi WrapperFactory sınıfında güçlü bir bağımlılığa sahiptir. Bu iyi değil. Bir başka iyileştirme, bu işlevselliği, eylem filtresinin yapıcısı içine enjekte edilecek bir arayüz halinde soyutlamak olabilir. Bu, uygulamanızın farklı katmanları arasındaki endişelerin daha fazla ayrılmasını sağlar.

+0

Benim berbat kodum Darin'i yeniden yazdığınız için teşekkürler. Bu benim için çalıştı. Tekrar teşekkürler :) – Praveen

+0

WrapperFactory'nin eylem filtresi oluşturucuya enjekte edilmesi hakkındaki yorumunuz beni meraklandırıyor. WrapFilterAttribute dekorasyonu ile WrapperFactory örneğini göndermeyi nasıl başarırsınız? AFAIK, nitelikler derleme zamanı değerleri (sabitler vb.) Gerektirir. – Praveen

+1

@Praveen, burada [eylem süzgeçleri ile kurucu enjeksiyonu] elde etmenin bir örneğidir (http://iridescence.no/post/Constructor-Injection-for-ASPNET-MVC-Action-Filters.aspx). Bu biraz hacky ama bu an için tek yol. Bu, ASP.NET MVC 3. –