1

Resolved

DataAttribute with an Enum in the constructor breaks in 2.x

description

This code works fine with the latest stable release from NuGet (1.9.2 as of this writing).
using System.Collections.Generic;
using System.Reflection;
using Xunit;
using Xunit.Extensions;

namespace ClassLibrary1
{
    public enum FooType
    {
        Bar,
        Baz
    }

    public class FooAttribute : DataAttribute
    {
        private string type;

        public FooAttribute(FooType type)
        {
            this.type = type.ToString();
        }

        public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, System.Type[] parameterTypes)
        {
            yield return new[] { type };
        }
    }

    public class Class1
    {
        [Theory]
        [Foo(FooType.Bar)]
        public void foo(string type)
        {
            Assert.True(true);
        }
    }
}
The same code, updated for 2.0, doesn't work with the latest alpha release from NuGet (xUnit.net 2.0.0-alpha-build2576 as of this writing).
using System.Collections.Generic;
using System.Reflection;
using Xunit;
using Xunit.Sdk;

namespace ClassLibrary1
{
    public enum FooType
    {
        Bar,
        Baz
    }

    public class FooAttribute : DataAttribute
    {
        private string type;

        public FooAttribute(FooType type)
        {
            this.type = type.ToString();
        }

        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            yield return new[] { type };
        }
    }

    public class Class1
    {
        [Theory]
        [Foo(FooType.Bar)]
        public void foo(string type)
        {
            Assert.True(true);
        }
    }
}
Result Message: System.MissingMethodException : Constructor on type 'ClassLibrary1.FooAttribute' not found.
Result StackTrace:
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, Object[] args)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
It works fine when the parameter is a String instead of an Enum.

I'm also using the latest test runner (0.99.3 as of this writing) with VS 2012.

Do I need to change something else for this to work with 2.x or is there a bug?

comments

BradWilson wrote Mar 15, 2014 at 4:49 PM

I believe this was "accidentally" working in v1.

Your parameter type should be the enum type, not the string type. The automatic type conversion is not an intended feature.

** Closed by BradWilson 03/15/2014 9:49AM

stijnherreman wrote Mar 17, 2014 at 10:17 AM

I'm not doing any automatic type conversion, I'm doing an explicit ToString() in the constructor. Here's an example that uses an int instead of an Enum, with no other differences, it's still doing an explicit ToString(). This one works fine.
using System.Collections.Generic;
using System.Reflection;
using Xunit;
using Xunit.Sdk;

namespace ClassLibrary1
{
    public enum FooType
    {
        Bar,
        Baz
    }

    public class FooAttribute : DataAttribute
    {
        private string type;

        public FooAttribute(int type)
        {
            this.type = type.ToString();
        }

        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            yield return new[] { type };
        }
    }

    public class Class1
    {
        [Theory]
        [Foo(5)]
        public void foo(string type)
        {
            Assert.True(true);
        }
    }
}
Test Passed - foo(type: "5")

stijnherreman wrote Mar 17, 2014 at 10:27 AM

For the record, the actual code is slightly more complex in a way that changing the test parameter from a string to the Enum is undesired.
[Theory]
[Driver(Driver.InternetExplorer)]
public void Foo(IWebDriver driver)

BradWilson wrote Mar 22, 2014 at 10:13 PM

Fixed in change set 9472276.