140

I'm trying to do a little Test-First development, and I'm trying to verify that my classes are marked with an attribute:

[SubControllerActionToViewDataAttribute]
public class ScheduleController : Controller

How do I unit test that the class has that attribute assigned to it?

JoshRivers
  • 9,920
  • 8
  • 39
  • 39

4 Answers4

158

check that

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

isn't null (Assert.IsNotNull or similar)

(the reason I use this rather than IsDefined is that most times I want to validate some properties of the attribute too....)

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 8
    to only check if the attribute is present, which is usually all that is needed for parameterless/propertyless attributes, it's cheaper to use .IsDefined, as it will query the metadata, and not deserialize and instantiate the attribute object. – Lasse V. Karlsen Aug 04 '09 at 07:52
  • 1
    As is the point about IsDefined being cheaper... but in most cases (and in particular unit tests) you are unlikely to notice the difference. Maybe if it was a tight loop in production code... – Marc Gravell Aug 04 '09 at 07:58
  • @Marc- I agree about that the difference in performance would probably not be noticeable in a unit test. I'd get the attribute if I needed to use it, which as you say is the scenario in most cases. I recently used IsDefined in a framework I was writing to exclude a column in a dropdown of sortable fields- this worked well as I didn't need to use to the attribute itself. – RichardOD Aug 04 '09 at 08:01
  • 1
    How can we test the same for a method? – Manvinder Singh Apr 23 '20 at 11:20
96

The same you would normally check for an attribute on a class.

Here's some sample code.

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

I think in many cases testing for the existence of an attribute in a unit test is wrong. As I've not used MVC contrib's sub controller functionality I can't comment whether it is appropriate in this case though.

RichardOD
  • 28,883
  • 9
  • 61
  • 81
23

It is also possible to use generics on this:

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

This way you do not need another typeof(...), which can make the code cleaner.

  • This does not work for me. Which `using` .. am I missing? –  Apr 19 '17 at 13:22
  • @Scanzy I'm not sure, are you not using a IDE? (Usually they suggest the correct `using`) What error do you get? – This company is turning evil. Apr 19 '17 at 13:23
  • 2
    ok, [here](https://msdn.microsoft.com/it-it/library/hh194292(v=vs.110).aspx) I found the `GetCustomAttribute` method is avaliable from .NET 4.5 and my IDE was set to 3.5 so everything is clear now –  Apr 19 '17 at 16:35
13

I know this thread is really old, but if somebody stumble upon on it you may find fluentassertions project very convenient for doing this kind of assertions.

typeof(MyPresentationModel).Should().BeDecoratedWith<SomeAttribute>();
Aleksey L.
  • 35,047
  • 10
  • 74
  • 84