Skip to main content

xUnit.net - testing for each value of an enum



Recently, I had to come up with a unit test to test a certain functionality for each value of an enum. Let's say the enum is something like this:

        public enum Number
        {
            One = 1,
            Two,
            Three,
            Four,
            Five,
            Six
        }

The unit test I wrote first was:

        [Theory]
        [InlineData(Number.One)]
        [InlineData(Number.Two)]
        [InlineData(Number.Three)]
        [InlineData(Number.Four)]
        [InlineData(Number.Five)]
        [InlineData(Number.Six)]
        public void TestNumber(Number number)
        {
            Assert.Equal(true, (Convert.ToInt32(number> 0));
        }

Though it worked fine for the given situation, I wanted a better way to do this so that that even if more values were added to the enum in the future, the test would still work without needing changes.

Fortunately, xUnit has ways to parameterize tests with data from members of a class using MemberData attribute (There is good material online about these attributes, eg: here).

The solution using MemberData is:

        public static IEnumerable<object[]> enumValues()
        {
            foreach (var number in Enum.GetValues(typeof(Number)))
            {
                yield return new object[] { number };
            }
        }
 
        [Theory]
        [MemberData("enumValues")]
        public void TestNumberGeneric(Number number)
        {
            Assert.Equal(true, (Convert.ToInt32(number> 0));
        }

With C# 6.0 and above, instead of using MemberData("enumValues"), we can use the nameof operator like MemberData(nameof(enumValues)) and avoid hard-coding the method name.



Comments

Post a Comment

Popular posts from this blog

Round to even cents

I did a coding assignment one of these days that needed me to round a given price to the nearest even cent. Though the requirement was a bit odd, it became interesting when I realized that the built-in rounding methods in .Net were not sufficient. 10.346 has to round to 10.34 10.356 has to round to 10.36 I wrote the following method to implement this:         public static decimal RoundToEvenCents( decimal sourceNumber)         {             var tempNumber = sourceNumber * 100;             var lowerValue = Math.Floor(tempNumber);             var upperValue = Math.Ceiling(tempNumber);             var evenValue = (lowerValue % 2 == 0) ? lowerValue : upperValue;             return evenValue / 100;         } Though I am not sure if this is a valid business requirement, putting it here just in case somebody needs it.