2010-11-11 8 views
2

Je voudrais effectuer une vérification dans le cadre d'un test unitaire qui utilise la réflexion pour vérifier certaines hypothèses, le code de base-psuedo pour ce serait comme suit:Exécution d'une vérification en utilisant la réflexion

  1. Pour chaque classe dans un assembly donné, localisez les classes de contrôleur (ASP.NET MVC2).

  2. Pour chaque action dans cette classe, localiser toutes celles qui sont décorées avec un attribut donné (Appelons cette TargetAttribute)

  3. Pour chacune de ces méthodes décorées avec l'attribut d'intérêt, assurer qu'au moins l'un des paramètres de la méthode d'action implémente une interface donnée (appelons cela ITarget).

Comment procéder pour effectuer une telle vérification? (Réponses en C# ou VB.NET sont les bienvenus)

Edit:

Je posterai le code final ici (traduit VB.NET) qui effectue cette vérification:

Dim ass As Assembly = Assembly.GetAssembly(GetType(Web.WebConfiguratorMarker)) 

    Dim methodsToCheck = ass.GetTypes(). 
         Where(Function(t) t.IsSubclassOf(GetType(Controller))). 
         SelectMany(Function(t) t.GetMethods()). 
         Where(Function(m) m.GetCustomAttributes(GetType(AutoValidateJsonModelAttribute), False).Length > 0). 
         Where(Function(m) m.ReturnType Is GetType(ActionResult)).ToArray() 

    For Each method In methodsToCheck 

     Dim implementsIValidatable As Boolean = False 

     For Each param In method.GetParameters() 
      If GetType(IValidatable).IsAssignableFrom(param.ParameterType) Then 
       implementsIValidatable = True 
       Exit For 
      End If 
     Next 

     Assert.True(implementsIValidatable, String.Format("Controller of type [{0}] has an action [{1}] that is decorated with <AutoValidateJsonModel()> but does not have a IValidatable instance as a param", method.DeclaringType, method.Name)) 

    Next 

Répondre

2
var assembly = System.Reflection.Assembly.GetExecutingAssembly(); 

var methods = assembly.GetTypes() 
       .Where(t => t is System.Web.Mvc.Controller) 
       .SelectMany(t => t.GetMethods()) 
       .Where(m => m.ReturnType is ActionResult) 
       .Where(m => m.GetCustomAttributes(typeof(TargetAttribute), false).Length > 0) 
       .ToArray(); 

bool implementsITarget = false; 

foreach(method in methods) 
{ 
    foreach(param in method.GetParameters()) 
    { 
     if(param.ParameterType is ITarget) 
     { 
      implementsITarget = true; 
      break; 
     } 
    } 
    Assert.True(implementsITarget , String.Format("Controller {0} has action {1} that does not implement ITarget but is decorated with TargetAttribute", method.DeclaringType, method.Name)); 
    implementsITarget = false; 
} 
+0

Cela semble très prometteur, merci! Quelques petites choses: je pense que la vérification du contrôleur serait mieux faite en vérifiant la classe de base, n'est-ce pas? par exemple. devrait hériter de la classe de contrôleur de base ... aussi, je ne suis pas sûr que je voudrais ignorer les types abstraits, comme je fais usage de l'héritage pour les contrôleurs ... autre que ces détails mineurs, cela ressemble à une bonne solution . – DanP

+0

@DanP: D'accord, fait quelques changements qui reflètent ce que vous avez suggéré. Vous avez parfaitement raison sur la vérification du nom du contrôleur, qui était moi paresseux: P – BeRecursive

+0

C'était presque exactement ce dont j'avais besoin ... la seule erreur flagrante est lorsque la comparaison de param est ITarget ... vous voulez param.ParameterType Is ITarget - très bonne réponse! – DanP

0

Votre audit est un gros problème pour un test unitaire qui n'aidera probablement pas à la qualité du code. MVC est censé être meilleur pour les tests unitaires, mais les tests unitaires ne sont pas utiles. Web Forms est beaucoup mieux à tout le reste en plus des tests unitaires, c'est donc un meilleur choix pour les applications d'entreprise.

+0

D'accord, ceci est plus d'un "test de convention"; il est simplement utile de l'inclure dans une suite de tests unitaires afin que ma construction se brise si elle échoue dans le cadre de notre processus de CI. – DanP

Questions connexes