Sprawdź, czy klasa ma atrybut?

101

Próbuję zrobić mały program Test-First i próbuję sprawdzić, czy moje klasy są oznaczone atrybutem:

[SubControllerActionToViewDataAttribute]
public class ScheduleController : Controller

Jak przeprowadzić test jednostkowy, czy klasa ma przypisany ten atrybut?

JoshRivers
źródło

Odpowiedzi:

123

Sprawdź to

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

nie jest null ( Assert.IsNotNulllub podobny)

(powodem, dla którego używam tego, a nie IsDefinedjest to, że w większości przypadków chcę również zweryfikować niektóre właściwości atrybutu ...)

Marc Gravell
źródło
6
aby sprawdzić tylko, czy atrybut jest obecny, co zwykle jest wszystkim, co jest potrzebne w przypadku atrybutów bez parametrów / właściwości, tańsze jest użycie .IsDefined, ponieważ będzie sprawdzać metadane, a nie deserializować i tworzyć wystąpienia obiektu atrybutu.
Lasse V. Karlsen
1
Jak chodzi o to, że IsDefined jest tańszy ... ale w większości przypadków (aw szczególności testów jednostkowych) prawdopodobnie nie zauważysz różnicy. Może gdyby to była wąska pętla w kodzie produkcyjnym ...
Marc Gravell
@ Marc- Zgadzam się, że różnica w wydajności prawdopodobnie nie byłaby zauważalna w teście jednostkowym. Otrzymałbym atrybut, gdybym musiał go użyć, co, jak mówisz, jest scenariuszem w większości przypadków. Niedawno użyłem IsDefined we frameworku, który pisałem, aby wykluczyć kolumnę z listy rozwijanej pól do sortowania - zadziałało to dobrze, ponieważ nie musiałem używać samego atrybutu.
RichardOD
Jak możemy przetestować to samo dla metody?
Manvinder Singh
80

To samo, co normalnie sprawdzasz dla atrybutu w klasie.

Oto przykładowy kod.

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

Myślę, że w wielu przypadkach testowanie istnienia atrybutu w teście jednostkowym jest błędne. Ponieważ nie korzystałem z funkcji kontrolera pomocniczego MVC contrib, nie mogę komentować, czy jest to odpowiednie w tym przypadku.

RichardOD
źródło
Zrobiłem +1, a następnie zauważyłem błąd. Powinien być .IsDefined (typeof (Type), false);
Alexander Beletsky
@alexanderb masz oczywiście rację. Zaktualizowałem teraz moją odpowiedź. Nie mogę wtedy porównywać mojej odpowiedzi z kompilatorem! Dzięki za wskazanie błędu
RichardOD
10
to podejście jest szybsze niż poprzednie
Slava
18

Możliwe jest również użycie w tym przypadku typów ogólnych:

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

W ten sposób nie potrzebujesz innego typeof(...), co może uczynić kod czystszym.

Kroltan
źródło
To nie działa dla mnie. Które using… brakuje mi?
@Scanzy Nie jestem pewien, czy nie używasz IDE? (Zazwyczaj sugerują poprawne using) Jaki błąd otrzymujesz?
Kroltan
1
ok, tutaj stwierdziłem, że GetCustomAttribute<SomeAttribute>metoda jest dostępna z .NET 4.5, a moje IDE było ustawione na 3.5 więc wszystko jest już jasne
9

Wiem, że ten wątek jest naprawdę stary, ale jeśli ktoś się na niego natknie, może się okazać, że projekt Fluentassertions jest bardzo wygodny do robienia tego typu twierdzeń.

typeof(MyPresentationModel).Should().BeDecoratedWith<SomeAttribute>();
Aleksey L.
źródło