TedOnTheNet
TedOnTheNet

Reputation: 1102

Mystery: my custom C# attribute is used once, but constructed numerous times while running a unit test. why?

I have a mystery I can't seem to resolve. I have this very simple unit test which uses a very simple custom Attribute. The attribute is added only to 1 class which is not even instantiated. I count the times the attribute is constructed. I would expect once, due to the attribute put on class MyDummyClass. But for some reason the unittest results in 2. If I add it to the class twice, the result is 4. If I add it to MyTestClass it is increased by 6 and if I add it to the MyTest another increase of 13 occurs. Thus having the attribute on MyDummyClass, MyTestClass and MyTest results in a count of 21. WHY!?

some extra tests I did:
- If I try this in a console app, it works as expected and results in 1.
- If I do this in a MsTest project and use the VS MsTest runner the result is 1.
- If I run the code in NUnit's own viewer (2.0 framework) or with resharper it is 21.
- Notable: if I run the MsTest test with resharper the result is 2. Seems resharper messes something up as well.

I am using VS2010 build 10.0.40219.1, Resharper v6.1.1000.82 and NUnit 2.5.10 (provided by R#)

Care to test it? go ahead, here's the code:

using System;
using NUnit.Framework;

namespace MyTests
{
    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    public class WtfAttribute : Attribute
    {
        public static int CallCount = 0;

        public WtfAttribute() //every time the attribute is constructed the count is incremented by 1.
        {
            CallCount++;
        }
    }

    //this class is NEVER instantiated, but adding the attribute to it increases the callcount by 2. I expected it to be 1 due to reflection.
    [Wtf]
    public class MyDummyClass
    {
    }

    [TestFixture]
    //adding the attribute to MyTestClass increases the callcount by 6.
    //[Wtf]
    public class MyTestClass
    {
        [Test]
        //adding the attribute to MyTest increases the callcount by 13.
        //[Wtf]
        public void MyTest()
        {
            Assert.AreEqual(1, WtfAttribute.CallCount, "CallCount = " + WtfAttribute.CallCount);
        }
    }
}

I hope anyone can help me figure out WTF is going on. Why isn't CallCount 1? Thanks for any help and comments offered.

Regards, Ted

Upvotes: 3

Views: 558

Answers (1)

RobSiklos
RobSiklos

Reputation: 8849

The reason is that the unit test frameworks inspect your assemblies using reflection, and they query the custom attributes on all assemblies, types, and methods.

When you do this (i.e. call GetCustomAttributes()), the attributes are constructed so that they can be returned in the result of that call.

I guess the unit test frameworks are doing this type of reflection multiple times.

Upvotes: 5

Related Questions