¿Prueba si una clase tiene un atributo?

101

Estoy tratando de hacer un pequeño desarrollo Test-First y estoy tratando de verificar que mis clases estén marcadas con un atributo:

[SubControllerActionToViewDataAttribute]
public class ScheduleController : Controller

¿Cómo hago la prueba unitaria de que la clase tiene ese atributo asignado?

JoshRivers
fuente

Respuestas:

123

Mira esto

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

no es nulo ( Assert.IsNotNullo similar)

(la razón por la que uso esto en lugar de IsDefinedes que la mayoría de las veces también quiero validar algunas propiedades del atributo ...)

Marc Gravell
fuente
6
para verificar solo si el atributo está presente, que generalmente es todo lo que se necesita para los atributos sin parámetros / sin propiedades, es más barato usar .IsDefined, ya que consultará los metadatos, y no deserializará ni instanciará el objeto de atributo.
Lasse V. Karlsen
1
Como es el punto de que IsDefined es más barato ... pero en la mayoría de los casos (y en las pruebas unitarias en particular) es poco probable que note la diferencia. Tal vez si fuera un circuito cerrado en el código de producción ...
Marc Gravell
@ Marc- Estoy de acuerdo en que la diferencia de rendimiento probablemente no se notará en una prueba unitaria. Obtendría el atributo si tuviera que usarlo, que como dices es el escenario en la mayoría de los casos. Recientemente usé IsDefined en un marco que estaba escribiendo para excluir una columna en un menú desplegable de campos ordenables; esto funcionó bien ya que no necesitaba usar el atributo en sí.
RichardOD
¿Cómo podemos probar lo mismo para un método?
Manvinder Singh
80

Lo mismo que normalmente buscaría un atributo en una clase.

Aquí tienes un código de muestra.

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

Creo que en muchos casos probar la existencia de un atributo en una prueba unitaria es incorrecto. Como no he usado la funcionalidad del subcontrolador de MVC contrib, no puedo comentar si es apropiado en este caso.

RichardOD
fuente
Hice +1 y luego notó un error. Debe ser .IsDefined (typeof (Type), false);
Alexander Beletsky
@alexanderb, por supuesto que tienes razón. Actualicé mi respuesta ahora. ¡No debí comparar mi respuesta con el compilador en ese momento! Gracias por señalar el error
RichardOD
10
este enfoque es más rápido que el anterior
Slava
18

También es posible utilizar genéricos en esto:

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

De esta manera, no necesita otro typeof(...), lo que puede hacer que el código sea más limpio.

Kroltan
fuente
Esto no funciona para mi. ¿Cuál using... me estoy perdiendo?
@Scanzy No estoy seguro, ¿no estás usando un IDE? (Por lo general, sugieren lo correcto using) ¿Qué error obtiene?
Kroltan
1
ok, aquí encontré que el GetCustomAttribute<SomeAttribute>método está disponible desde .NET 4.5 y mi IDE se configuró en 3.5, por lo que todo está claro ahora
9

Sé que este hilo es muy antiguo, pero si alguien se topa con él, es posible que el proyecto fluentassertions sea muy conveniente para hacer este tipo de afirmaciones.

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