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?

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 ...)


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.


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.


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>();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.