2010-03-02 5 views
4

Dans un ActionFilter personnalisé, je veux vérifier les attributs de l'action du contrôleur qui sera exécutée. Traversant une petite application de test, les travaux suivants lors du lancement de l'application dans le développement asp.net Serveur-Unité testant un ActionFilter - configuration correcte du 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) 
    { 
     // ... 
    } 
} 

Une méthode d'action sans SomeAttribute lancers francs une ArgumentException et inversement, une méthode d'action avec SomeAttribute ne fonctionne pas. Jusqu'ici tout va bien.

Maintenant, je voudrais configurer des tests unitaires pour le filtre ActionFilter, mais comment puis-je configurer la méthode d'action sur laquelle la méthode OnActionExecuting doit s'exécuter dans le test unitaire? L'utilisation du code suivant ne trouve pas SomeAttribute sur la méthode d'action qui sera exécutée. Le test est-il correctement configuré? N'ai-je pas arrangé quelque chose correctement dans le test? Pour clarifier les choses, le test n'est pas complet, mais je ne suis pas sûr de ce que j'ai manqué de telle sorte que someAttribute dans OnActionExecuting dans le test est 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(); 
     } 
    } 

Répondre

5

Depuis la propriété ActionDescriptor de ActionExecutingContext est virtuel, il vous suffit de override que et fournissez votre propre implémentation de ActionDescriptor.

Voici deux tests qui vérifient les deux branches grâce à la mise en œuvre actuelle de 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 
} 
Questions connexes