Tester si une classe a un attribut?

101

J'essaie de faire un petit développement Test-First, et j'essaie de vérifier que mes classes sont marquées d'un attribut:

[SubControllerActionToViewDataAttribute]
public class ScheduleController : Controller

Comment tester unitaire que la classe a cet attribut qui lui est attribué?

JoshRivers
la source

Réponses:

123

regarde ça

Attribute.GetCustomAttribute(typeof(ScheduleController),
    typeof(SubControllerActionToViewDataAttribute))

n'est pas nul ( Assert.IsNotNullou similaire)

(la raison pour laquelle j'utilise ceci plutôt que IsDefinedc'est que la plupart du temps, je veux valider certaines propriétés de l'attribut aussi ....)

Marc Gravell
la source
6
pour vérifier uniquement si l'attribut est présent, ce qui est généralement tout ce qui est nécessaire pour les attributs sans paramètre / sans propriété, il est moins coûteux d'utiliser .IsDefined, car il interrogera les métadonnées, et ne désérialisera et instanciera pas l'objet attribut.
Lasse V. Karlsen
1
Comme le fait qu'IsDefined soit moins cher ... mais dans la plupart des cas (et en particulier les tests unitaires), il est peu probable que vous remarquiez la différence. Peut-être que si c'était une boucle serrée dans le code de production ...
Marc Gravell
@ Marc- Je suis d'accord sur le fait que la différence de performance ne serait probablement pas perceptible dans un test unitaire. J'obtiendrais l'attribut si j'avais besoin de l'utiliser, ce qui, comme vous le dites, est le scénario dans la plupart des cas. J'ai récemment utilisé IsDefined dans un cadre que j'écrivais pour exclure une colonne dans une liste déroulante de champs triables - cela a bien fonctionné car je n'avais pas besoin de l'utiliser pour l'attribut lui-même.
RichardOD
Comment pouvons-nous tester la même chose pour une méthode?
Manvinder Singh
80

La même chose que vous vérifieriez normalement pour un attribut sur une classe.

Voici un exemple de code.

typeof(ScheduleController)
.IsDefined(typeof(SubControllerActionToViewDataAttribute), false);

Je pense que dans de nombreux cas, tester l'existence d'un attribut dans un test unitaire est faux. Comme je n'ai pas utilisé la fonctionnalité de sous-contrôleur de MVC contrib, je ne peux pas dire si cela est approprié dans ce cas.

RichardOD
la source
A fait +1, puis a remarqué une erreur. Il doit être .IsDefined (typeof (Type), false);
Alexander Beletsky
@alexanderb vous avez bien sûr raison. J'ai mis à jour ma réponse maintenant. Je ne dois pas vérifier ma réponse par rapport au compilateur à l'époque! Merci d'avoir signalé l'erreur
RichardOD
10
cette approche est plus rapide que la précédente
Slava
18

Il est également possible d'utiliser des génériques sur ceci:

var type = typeof(SomeType);
var attribute = type.GetCustomAttribute<SomeAttribute>();

De cette façon, vous n'avez pas besoin d'un autre typeof(...), ce qui peut rendre le code plus propre.

Kroltan
la source
Cela ne fonctionne pas pour moi. Lequel using.. suis-je absent?
@Scanzy Je ne suis pas sûr, n'utilisez-vous pas un IDE? (Habituellement, ils suggèrent la bonne using) Quelle erreur obtenez-vous?
Kroltan
1
ok, ici j'ai trouvé que la GetCustomAttribute<SomeAttribute>méthode est disponible à partir de .NET 4.5 et que mon IDE a été réglé sur 3.5 donc tout est clair maintenant
9

Je sais que ce fil est vraiment vieux, mais si quelqu'un tombe dessus, vous trouverez peut-être un projet d' assertions fluentes très pratique pour faire ce genre d'assertions.

typeof(MyPresentationModel).Should().BeDecoratedWith<SomeAttribute>();
Aleksey L.
la source