Seb*_*Seb 10 unit-testing xunit autofixture
我正面临一个有趣的问题.我发现AutoDataAttribute可用于最小化测试的"排列"部分(通过ctor传递的依赖关系).真棒!
例:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{ }
}
[Theory, AutoMoqData]
public void Process_ValidContext_CallsK2Workflows(
[Frozen]Mock<IK2Datasource> k2,
[Frozen]Mock<IAppConfiguration> config,
PrBatchApproveBroker sut)
{
(...)
}
Run Code Online (Sandbox Code Playgroud)
现在我想使用这个伟大的功能,并将自己的数据注入到这个理论中:
[Theory, AutoMoqData, MemberData("Data")]
public void ExtractPayments_EmptyInvoiceNumber_IgnoresRecordsWithEmptyInvoiceNumber(
[Frozen]Mock<IExcelDatasource> xls,
SunSystemExcelDatasource sut,
List<Row> rows,
int expectedCount)
{
(...)
}
Run Code Online (Sandbox Code Playgroud)
问题:AutoData属性将为我生成随机数据.我发现的唯一方法是摆脱AutoData属性并使用MemberData.如果我这样做,我需要自己处理对象实例化:))...
有没有办法同时传递我的类和一些"硬编码"数据?
谢谢你,Seb
有没有办法同时传递我的类和一些"硬编码"数据?
一种方法是通过属性提供一些内联值,并让AutoFixture填充其余的内容.
[Theory, InlineAutoMoqData(3)]
public void ExtractPayments_EmptyInvoiceNumber_IgnoresRecordsWithEmptyInvoiceNumber(
int expectedCount,
[Frozen]Mock<IExcelDatasource> xls,
SunSystemExcelDatasource sut,
List<Row> rows)
{
// expectedCount is 3.
}
Run Code Online (Sandbox Code Playgroud)
请注意,我必须移动expectedCount才能成为第一个参数,并使用InlineAutoMoqData定义为的自定义属性:
internal class AutoMoqDataAttribute : AutoDataAttribute
{
internal AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
internal class InlineAutoMoqDataAttribute : CompositeDataAttribute
{
internal InlineAutoMoqDataAttribute(params object[] values)
: base(
new DataAttribute[] {
new InlineDataAttribute(values),
new AutoMoqDataAttribute() })
{
}
}
Run Code Online (Sandbox Code Playgroud)
您必须创建自己的自定义 DataAttribute。这就是你可以作曲的方式。
/// <summary>
/// Helper DataAttribute to use the regular xUnit based DataAttributes with AutoFixture and Mocking capabilities.
/// </summary>
/// <seealso cref="Xunit.Sdk.DataAttribute" />
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class AutoCompositeDataAttribute : DataAttribute
{
/// <summary>
/// The attributes
/// </summary>
private readonly DataAttribute baseAttribute;
/// <summary>
/// The automatic data attribute
/// </summary>
private readonly DataAttribute autoDataAttribute;
/// <summary>
/// Initializes a new instance of the <see cref="AutoCompositeDataAttribute" /> class.
/// </summary>
/// <param name="baseAttribute">The base attribute.</param>
/// <param name="autoDataAttribute">The automatic data attribute.</param>
public AutoCompositeDataAttribute(DataAttribute baseAttribute, DataAttribute autoDataAttribute)
{
this.baseAttribute = baseAttribute;
this.autoDataAttribute = autoDataAttribute;
}
/// <summary>
/// Returns the data to be used to test the theory.
/// </summary>
/// <param name="testMethod">The method that is being tested</param>
/// <returns>
/// One or more sets of theory data. Each invocation of the test method
/// is represented by a single object array.
/// </returns>
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
if (testMethod == null)
{
throw new ArgumentNullException(nameof(testMethod));
}
var data = this.baseAttribute.GetData(testMethod);
foreach (var datum in data)
{
var autoData = this.autoDataAttribute.GetData(testMethod).ToArray()[0];
for (var i = 0; i < datum.Length; i++)
{
autoData[i] = datum[i];
}
yield return autoData;
}
}
}
/// <summary>
/// Member auto data implementation based on InlineAutoDataAttribute and MemberData
/// </summary>
/// <seealso cref="Ploeh.AutoFixture.Xunit2.CompositeDataAttribute" />
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MemberAutoDataAttribute : AutoCompositeDataAttribute
{
/// <summary>
/// The automatic data attribute
/// </summary>
private readonly AutoDataAttribute autoDataAttribute;
/// <summary>
/// Initializes a new instance of the <see cref="MemberAutoDataAttribute" /> class.
/// </summary>
/// <param name="memberName">Name of the member.</param>
/// <param name="parameters">The parameters.</param>
public MemberAutoDataAttribute(string memberName, params object[] parameters)
: this(new AutoDataAttribute(), memberName, parameters)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MemberAutoDataAttribute" /> class.
/// </summary>
/// <param name="autoDataAttribute">The automatic data attribute.</param>
/// <param name="memberName">Name of the member.</param>
/// <param name="parameters">The parameters.</param>
public MemberAutoDataAttribute(AutoDataAttribute autoDataAttribute, string memberName, params object[] parameters)
: base((DataAttribute)new MemberDataAttribute(memberName, parameters), (DataAttribute)autoDataAttribute)
{
this.autoDataAttribute = autoDataAttribute;
}
/// <summary>
/// Gets the automatic data attribute.
/// </summary>
/// <value>
/// The automatic data attribute.
/// </value>
public AutoDataAttribute AutoDataAttribute => this.autoDataAttribute;
}
Run Code Online (Sandbox Code Playgroud)
如果你想启用 Moq,那么扩展它以获得
/// <summary>
/// The member auto moq data attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MemberAutoMoqDataAttribute : MemberAutoDataAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="MemberAutoMoqDataAttribute"/> class.
/// </summary>
/// <param name="memberName">Name of the member.</param>
/// <param name="parameters">The parameters.</param>
public MemberAutoMoqDataAttribute(string memberName, params object[] parameters)
: base(new AutoMoqDataAttribute(), memberName, parameters)
{
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2468 次 |
| 最近记录: |