【问题标题】:Xunit inline auto data with autofixture questionXunit 内联自动数据与自动夹具问题
【发布时间】:2021-07-31 16:24:38
【问题描述】:

我创建了一个自定义内联自动起订量属性,如下所示:

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(() =>{
            var fixture = new Fixture().Customize(new CompositeCustomization(
                new AutoMoqCustomization(),
                new SupportMutableValueTypesCustomization()));
            fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => 
            fixture.Behaviors.Remove(b));
            fixture.Behaviors.Add(new OmitOnRecursionBehavior());
            return fixture;}){}
}

public class InlineAutoMoqData : InlineAutoDataAttribute
{
    public InlineAutoMoqData(params object[] objects) : base(new AutoMoqDataAttribute(), objects)
    {

    } 
}

我喜欢 autofixture,因为如果我没有通过属性提供测试数据,它会自动为我填充数据。到目前为止,我可以使用内联数据来传递 null、字符串、int 等,但是如何传递空列表或对象?例如下面的测试方法。请随时修改我的代码以使其正常工作,因为我对单元测试很陌生。

    [Theory]
    [InlineAutoMoqData(null)]
    public void UpdatePortfolioFiles_InvalidInput_ShouldThrowException(List<MyClass> mytestList, MyTestService sut)
    {
       
        //do something here
       
    }enter code here

【问题讨论】:

    标签: c# asp.net-core xunit autofixture


    【解决方案1】:

    您描述的场景听起来像是MemberAutoDataAttribute 的一个很好的用例。此属性类似于 xUnit 中的 MemberDataAttribute,它应该允许您从静态成员(字段/属性/方法)向测试方法提供参数。

    MemberAutoDataAttribute 目前存在一个错误,它仅提供来自成员的第一组参数。社区成员here 发布了一个解决方法。

    我会尽快修复该属性。

    public static IEnumerable<object[]> TestCases()
    { 
        yield return new object[] { new List<MyClass>() };
        yield return new object[] { new HashSet<MyClass>() };
        yield return new object[] { new LinkedList<MyClass>() };
    }
    
    [Theory]
    [MemberDomainData(nameof(TestCases))]
    public void UpdatePortfolioFiles_InvalidInput_ShouldThrowException(
        IEnumerable<MyClass> mytestList, MyClass sut)
    {
        Assert.Empty(mytestList);
        Assert.NotNull(sut);
    }
    
    public class MemberDomainData : MemberAutoDataAttribute
    {
        public MemberDomainData(string memberName, params object[] parameters)
            : base(new DomainDataAttribute(), memberName, parameters)
        {
        }
    }
    

    如果您不想使用解决方法实现,您可以使用声明性语法来创建空集合,直到修复出现。

    如果这能解决您的问题,请告诉我。

    作为建议,您可以将递归省略行为封装在单独的自定义中。自定义是小型可重复使用和可组合的。

    public class OmitRecursionCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b =>
            fixture.Behaviors.Remove(b));
            fixture.Behaviors.Add(new OmitOnRecursionBehavior());
        }
    }
    
    public class DomainCustomization : CompositeCustomization
    {
        public DomainCustomization()
            : base(
                new AutoMoqCustomization(),
                new SupportMutableValueTypesCustomization(),
                new OmitRecursionCustomization())
        {
        }
    }
    
    public class DomainDataAttribute : AutoDataAttribute
    {
        public DomainDataAttribute()
            : base(() => new Fixture().Customize(new DomainCustomization()))
        {
        }
    }
    

    【讨论】:

    • 非常感谢!使用 MemberAutoDataAttribute 的解决方法实现解决了我的问题。
    • 如果测试方法有第二个参数是字符串,如下所示。 public void UpdatePortfolioFiles_InvalidInput_ShouldThrowException(List&lt;VendorPortfolioFile&gt; vendorPortfolioFiles, string email, VendorPortfolioFileService sut) 使用 MemberAutoDataAttribute 传递电子邮件的正确方法是什么?
    • 您只需从提供测试用例的成员向 yield 语句添加一个附加值。 yield return new object[] { new List&lt;MyClass&gt;(), "admin@example.com" };
    猜你喜欢
    • 2017-04-04
    • 2011-08-25
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 2019-01-01
    • 2017-04-10
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多