2010-03-02 1 views
4

В пользовательском ActionFilter я хочу проверить атрибуты действия контроллера, которое будет выполнено. Запуск через небольшое тестовое приложение, следующие работы при запуске приложения в развитии asp.net Сервер-Тестирование модуля ActionFilter - правильная настройка ActionExecutingContext

public class CustomActionFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var someAttribute = filterContext.ActionDescriptor 
            .GetCustomAttributes(typeof(SomeAttribute), false) 
            .Cast<SomeAttribute>() 
            .SingleOrDefault(); 

     if (someAttribute == null) 
     { 
      throw new ArgumentException(); 
     } 

     // do something here 
    } 

    public override void OnActionExecuted(ActionExecutingContext filterContext) 
    { 
     // ... 
    } 
} 

Метод действия без SomeAttribute бросает ArgumentException и, наоборот, способ действия с SomeAttribute не делает. Все идет нормально.

Теперь я хотел бы установить некоторые модульные тесты для ActionFilter, но как я могу настроить метод действия, по которому должен быть запущен метод OnActionExecuting в модульном тесте? Используя следующий код, вы не найдете SomeAttribute о методе действия, который будет выполнен. Правильно ли установлен тест? Разве я не устроил что-то правильно в тесте? Для того, чтобы уточнить, тест не является полным, но я не уверен, что я пропустил такое, что someAttribute в OnActionExecuting в тесте null

[TestMethod] 
    public void Controller_With_SomeAttribute() 
    { 
     FakeController fakeController = 
      new FakeController(); 

     ControllerContext controllerContext = 
      new ControllerContext(new Mock<HttpContextBase>().Object, 
            new RouteData(), 
            fakeController); 

     var actionDescriptor = new Mock<ActionDescriptor>(); 
     actionDescriptor.SetupGet(x => x.ActionName).Returns("Action_With_SomeAttribute"); 

     ActionExecutingContext actionExecutingContext = 
      new ActionExecutingContext(controllerContext, 
             actionDescriptor.Object, 
             new RouteValueDictionary()); 

     CustomActionFilterAttribute customActionFilterAttribute = new CustomActionFilterAttribute(); 
     customActionFilterAttribute.OnActionExecuting(actionExecutingContext); 
    } 

    private class FakeController : Controller 
    { 
     [SomeAttribute] 
     ActionResult Action_With_SomeAttribute() 
     { 
      return View(); 
     } 
    } 

ответ

5

Поскольку ActionDescriptor свойство ActionExecutingContext является виртуальным, вы можете просто override что и обеспечить вашу собственную реализацию ActionDescriptor.

Вот два теста, которые проверяют две ветви по текущей реализации OnActionExecuting:

[ExpectedException(typeof(ArgumentException))] 
[TestMethod] 
public void OnActionExecutingWillThrowWhenSomeAttributeIsNotPresent() 
{ 
    // Fixture setup 
    var ctxStub = new Mock<ActionExecutingContext>(); 
    ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false)) 
     .Returns(new object[0]); 

    var sut = new CustomActionFilterAttribute(); 
    // Exercise system 
    sut.OnActionExecuting(ctxStub.Object); 
    // Verify outcome (expected exception) 
    // Teardown 
} 

[TestMethod] 
public void OnActionExecutingWillNotThrowWhenSomeAttributeIsPresent() 
{ 
    // Fixture setup 
    var ctxStub = new Mock<ActionExecutingContext>(); 
    ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false)) 
     .Returns(new object[] { new SomeAttribute() }); 

    var sut = new CustomActionFilterAttribute(); 
    // Exercise system 
    sut.OnActionExecuting(ctxStub.Object); 
    // Verify outcome (no exception indicates success) 
    // Teardown 
}