[Theory] [AutoMoqPropertyData("TestData")] public void ShouldMapEnum(MsgData msgData, CustomEnum expectedEnum, SomeObject sut) { var customEnum = sut.GetEnum(msgData); Assert.Equal(expectedEnum, customEnum); }
AutoMoqPropertyData实现:
public class AutoMoqPropertyDataAttribute : CompositeDataAttribute { public AutoMoqPropertyDataAttribute(string dataProperty) : base(new DataAttribute[] { new PropertyDataAttribute(dataProperty), new AutoDataAttribute(new Fixture().Customize(new AutoMoqCustomization())) }) { } }
System.InvalidOperationException: Expected 3 parameters, got 2 parameters at Ploeh.AutoFixture.Xunit.CompositeDataAttribute.d__0.MoveNext() at Xunit.Extensions.TheoryAttribute.d__7.MoveNext() at Xunit.Extensions.TheoryAttribute.EnumerateTestCommands(IMethodInfo method) Result StackTrace: at Xunit.Extensions.TheoryAttribute.c__DisplayClass5.b__1() at Xunit.Extensions.TheoryAttribute.LambdaTestCommand.Execute(Object testClass)
您必须按照Ruben Bartelink 指出的 答案中所述提供测试用例。
[Theory] [AutoMoqPropertyData("Case1")] [AutoMoqPropertyData("Case2")] [AutoMoqPropertyData("Case3")] [AutoMoqPropertyData("Case4")] public void ShouldMapEnum( MsgData msgData, CustomEnum expectedEnum, SomeObject sut) { var customEnum = sut.GetEnum(msgData); Assert.Equal(expectedEnum, customEnum); } public static IEnumerable
[PropertyAutoData("ColorPairs", Scope = AutoDataScope.Test)] // default is TestCase
你也可以和SubSpec的Thesis一起使用它:
[Thesis] [PropertyAutoData("ColorPairs")] public void ReverseColors([TestCaseParameter] TestData testData, int autoGenValue)
要在Moq中使用它,你需要扩展它,即
public class PropertyMockAutoDataAttribute : PropertyAutoDataAttribute { public PropertyFakeAutoDataAttribute(string propertyName) : base(propertyName, new Fixture().Customize(new AutoMoqCustomization())) { } }
这是代码:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using Ploeh.AutoFixture.Xunit; using Xunit.Extensions; /// /// Provides a data source for a data theory, with the data coming from a public static property on the test class combined with auto-generated data specimens generated by AutoFixture. /// public class PropertyAutoDataAttribute : AutoDataAttribute { private readonly string _propertyName; public PropertyAutoDataAttribute(string propertyName) { _propertyName = propertyName; } public PropertyAutoDataAttribute(string propertyName, IFixture fixture) : base(fixture) { _propertyName = propertyName; } /// /// Gets or sets the scope of auto-generated data. /// public AutoDataScope Scope { get; set; } public override IEnumerable GetData(MethodInfo methodUnderTest, Type[] parameterTypes) { var parameters = methodUnderTest.GetParameters(); var testCaseParametersIndices = GetTestCaseParameterIndices(parameters); if (!testCaseParametersIndices.Any()) { throw new InvalidOperationException(string.Format("There are no parameters marked using {0}.", typeof(TestCaseParameterAttribute).Name)); } if (testCaseParametersIndices.Length == parameters.Length) { throw new InvalidOperationException(string.Format("All parameters are provided by the property. Do not use {0} unless there are other parameters that AutoFixture should provide.", typeof(PropertyDataAttribute).Name)); } // 'split' the method under test in 2 methods: one to get the test case data sets and another one to get the auto-generated data set var testCaseParameterTypes = parameterTypes.Where((t, i) => testCaseParametersIndices.Contains(i)).ToArray(); var testCaseMethod = CreateDynamicMethod(methodUnderTest.Name + "_TestCase", testCaseParameterTypes); var autoFixtureParameterTypes = parameterTypes.Where((t, i) => !testCaseParametersIndices.Contains(i)).ToArray(); var autoFixtureTestMethod = CreateDynamicMethod(methodUnderTest.Name + "_AutoFixture", autoFixtureParameterTypes); // merge the test case data and the auto-generated data into a new array and yield it // the merge depends on the Scope: // * if the scope is TestCase then auto-generate data once for all tests // * if the scope is Test then auto-generate data for every test var testCaseDataSets = GetTestCaseDataSets(methodUnderTest.DeclaringType, testCaseMethod, testCaseParameterTypes); object[] autoGeneratedDataSet = null; if (Scope == AutoDataScope.TestCase) { autoGeneratedDataSet = GetAutoGeneratedData(autoFixtureTestMethod, autoFixtureParameterTypes); } var autoFixtureParameterIndices = Enumerable.Range(0, parameters.Length).Except(testCaseParametersIndices).ToArray(); foreach (var testCaseDataSet in testCaseDataSets) { if (testCaseDataSet.Length != testCaseParameterTypes.Length) { throw new ApplicationException("There is a mismatch between the values generated by the property and the test case parameters."); } var mergedDataSet = new object[parameters.Length]; CopyAtIndices(testCaseDataSet, mergedDataSet, testCaseParametersIndices); if (Scope == AutoDataScope.Test) { autoGeneratedDataSet = GetAutoGeneratedData(autoFixtureTestMethod, autoFixtureParameterTypes); } CopyAtIndices(autoGeneratedDataSet, mergedDataSet, autoFixtureParameterIndices); yield return mergedDataSet; } } private static int[] GetTestCaseParameterIndices(ParameterInfo[] parameters) { var testCaseParametersIndices = new List(); for (var index = 0; index < parameters.Length; index++) { var parameter = parameters[index]; var isTestCaseParameter = parameter.GetCustomAttributes(typeof(TestCaseParameterAttribute), false).Length > 0; if (isTestCaseParameter) { testCaseParametersIndices.Add(index); } } return testCaseParametersIndices.ToArray(); } private static MethodInfo CreateDynamicMethod(string name, Type[] parameterTypes) { var method = new DynamicMethod(name, typeof(void), parameterTypes); return method.GetBaseDefinition(); } private object[] GetAutoGeneratedData(MethodInfo method, Type[] parameterTypes) { var autoDataSets = base.GetData(method, parameterTypes).ToArray(); if (autoDataSets == null || autoDataSets.Length == 0) { throw new ApplicationException("There was no data automatically generated by AutoFixture"); } if (autoDataSets.Length != 1) { throw new ApplicationException("Multiple sets of data were automatically generated. Only one was expected."); } return autoDataSets.Single(); } private IEnumerable GetTestCaseDataSets(Type testClassType, MethodInfo method, Type[] parameterTypes) { var attribute = new PropertyDataAttribute(_propertyName) { PropertyType = testClassType }; return attribute.GetData(method, parameterTypes); } private static void CopyAtIndices(object[] source, object[] target, int[] indices) { var sourceIndex = 0; foreach (var index in indices) { target[index] = source[sourceIndex++]; } } } /// /// Defines the scope of auto-generated data in a theory. /// public enum AutoDataScope { /// /// Data is auto-generated only once for all tests. /// TestCase, /// /// Data is auto-generated for every test. /// Test } /// /// Indicates that the parameter is part of a test case rather than being auto-generated by AutoFixture. /// [AttributeUsage(AttributeTargets.Parameter)] public class TestCaseParameterAttribute : Attribute { }