The easiest and safest way is to use the constructor accepting an IEnumerable<T>
. With modern C# this looks like this:
public class TestClass
{
public static readonly TheoryData<MyEnum> TestData = new(Enum.GetValues<MyEnum>());
[Theory]
[MemberData(nameof(TestData))]
public void TestMethod(MyEnum value)
{
// Arrange, Act, Assert
}
}
Be aware that MyEnum
needs to be defined in the project where TestClass
is defined, otherwise the test will just not run. It seems like this is a bug in xUnit or test explorer / runner. In VS you can see this because the test explorer cannot discover the tests when MyEnum
is defined in another project.
Often the enum is defined in another project, so we need a solution for this case.
Currently, I use TheoryData<string>
to pass the enum values as string
to the test method and then convert this string back to the actual enum values.
public class TestClass
{
public static readonly TheoryData<string> TestData = new(Enum.GetNames<MyEnum>());
[Theory]
[MemberData(nameof(TestData))]
public void TestMethod(string value)
{
// Arrange
var valueTyped = Enum.Parse<MyEnum>(value);
// Act, Assert
}
}
ToTheoryData<T>
extension method that does what you want. Internally, it could create theTheoryData<T>
object, transform each source item based on the expression you provide, add those results and then return the object. – NewkirkTheoryData
so that there is compiler time type checking?TheoryData
ultimately returns a set of objects (object[]
) on each iteration so it can be used with aClassData
attribute, they could still have the wrong type.class TestSpecificData : TheoryData<string, int>
andclass TestSpecificData2 : TheoryData<int, string>
both compiled just fine when used as data in this test:[ClassData(typeof(TestSpecificData))] [ClassData(typeof(TestSpecificData2))] public void UnitTest1(string a, int b)
but fail at runtime. – Bloomy