2010-10-01 24 views
6

Tôi đã thực hiện tìm kiếm trên SO và có vẻ như câu hỏi này được hỏi khá thường xuyên. Tôi đã có thể nhận được các mocks làm việc và tôi cũng có thể thực hiện OnActionExecuted() mà không có bất kỳ vấn đề. Đây là Bài kiểm tra đơn vị của tôi. Các dòng nhận xét là những dòng thất bại và tôi chắc chắn rằng tôi không chế nhạo đúng loại.Đơn vị kiểm tra bộ lọc hành động - Làm thế nào để chế tạo 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); 

Đây là bộ lọc hành động của tôi.

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

Vấn đề tôi đang gặp phải ở đây là filterContext.Result luôn xuất hiện dưới dạng EmptyResult. Tôi muốn đẩy vào một ViewResult ngậm nước thay thế. Bất kỳ ý tưởng làm thế nào tôi có thể thực hiện điều này?

Rất cám ơn!

Trả lời

9

Đầu tiên chúng ta hãy bắt đầu bằng cách sửa chữa lọc hành động của bạn như hiện nay mã trông xấu và những đúc có thể mang lại cho bạn đau đầu:

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

Và kiểm tra đơn vị:

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

Ghi chú: lọc hành động của bạn có sự phụ thuộc mạnh mẽ vào lớp học WrapperFactory. Điều này không tốt. Một cải tiến hơn nữa sẽ là trừu tượng hóa chức năng này thành một giao diện sẽ được đưa vào trong hàm tạo của bộ lọc hành động. Điều này sẽ cho phép bạn tách biệt hơn nữa mối quan tâm giữa các lớp khác nhau của ứng dụng của bạn.

+0

Cảm ơn bạn đã tái cấu trúc mã độc của tôi Darin. Điều này làm việc cho tôi. Cảm ơn một lần nữa :) – Praveen

+0

bình luận của bạn về tiêm WrapperFactory vào constructor bộ lọc hành động làm cho tôi tò mò. Làm thế nào bạn sẽ thực hiện việc gửi trong một thể hiện của WrapperFactory thông qua trang trí WrapFilterAttribute? AFAIK, các thuộc tính yêu cầu các giá trị biên dịch-thời gian (hằng số vv). – Praveen

+1

@Praveen, đây là một ví dụ về cách đạt được [constructor injection với bộ lọc hành động] (http://iridescence.no/post/Constructor-Injection-for-ASPNET-MVC-Action-Filters.aspx). Đó là một chút hacky nhưng đó là cách duy nhất cho thời điểm này. Điều này đã được cải thiện trong ASP.NET MVC 3. –

Các vấn đề liên quan