gpt4 book ai didi

abstract-class - AutoFixture 可以省略类层次结构之间的递归吗?

转载 作者:行者123 更新时间:2023-12-02 02:57:31 27 4
gpt4 key购买 nike

考虑以下方式来代表家庭成员:

public abstract class Human { }
public abstract class Child : Human
{
public ICollection<Parent> Parents { get; set; }
}
public abstract class Parent : Human
{
public ICollection<Child> Children { get; set; }
}
public class Son : Child { }
public class Daughter : Child { }
public class Mum : Parent { }
public class Dad : Parent { }

现在,我要 AutoFixture生成 Parent ,在 Mum 之间随机选择和 Dad ,以及在 Son 之间随机选择 child 的地方和 Daughter .我也希望它省略递归,所以如果它来自 Parent并生成 Child , 可以省略回 Parent 的链接.

我尝试了以下自定义:
var fixture = new Fixture();

fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());

var random = new Random();
fixture.Register<Parent>(() =>
{
switch (random.Next(1, 2))
{
case 1:
return fixture.Create<Mum>();
case 2:
return fixture.Create<Dad>();
default:
throw new NotImplementedException();
}
});
fixture.Register<Child>(() =>
{
switch (random.Next(1, 2))
{
case 1:
return fixture.Create<Son>();
case 2:
return fixture.Create<Daughter>();
default:
throw new NotImplementedException();
}
});

fixture.Create<Parent>();

但它抛出一个 InvalidCastException (见下文)。

有没有办法配置 AutoFixture 以便它考虑 Parent -> Child -> Parent递归,即使它实际上为每个实例随机选择了一个合适的子类?
Unhandled Exception: AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to
create an instance from AutoFixtureAbstractTrees.Parent because creation unexpectedly
failed with exception. Please refer to the inner exception to investigate the root cause of
the failure.

Request path:
AutoFixtureAbstractTrees.Mum
System.Collections.Generic.ICollection`1[AutoFixtureAbstractTrees.Child] Children
System.Collections.Generic.ICollection`1[AutoFixtureAbstractTrees.Child]
System.Collections.Generic.List`1[AutoFixtureAbstractTrees.Child]
System.Collections.Generic.IEnumerable`1[AutoFixtureAbstractTrees.Child] collection
System.Collections.Generic.IEnumerable`1[AutoFixtureAbstractTrees.Child]
AutoFixtureAbstractTrees.Child
AutoFixtureAbstractTrees.Son
System.Collections.Generic.ICollection`1[AutoFixtureAbstractTrees.Parent] Parents
System.Collections.Generic.ICollection`1[AutoFixtureAbstractTrees.Parent]
System.Collections.Generic.List`1[AutoFixtureAbstractTrees.Parent]
System.Collections.Generic.IEnumerable`1[AutoFixtureAbstractTrees.Parent] collection
System.Collections.Generic.IEnumerable`1[AutoFixtureAbstractTrees.Parent]
AutoFixtureAbstractTrees.Parent

Inner exception messages:
System.InvalidCastException: Unable to cast object of type
'AutoFixture.Kernel.OmitSpecimen' to type 'AutoFixtureAbstractTrees.Mum'.

最佳答案

您遇到此问题的原因是 AutoFixture 中的设计缺陷。当您使用 Create扩展方法,您本质上启动了一个新的解析上下文,而递归保护机制不会捕捉到它。

看起来,在这种情况下,您可以使用 ISpecimenBuilder 解决该问题。 s 和 Resolve来自 context而不是使用 Create扩展方法:

[Fact]
public void WorkAround()
{
var fixture = new Fixture();

fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior(3));

var random = new Random();
fixture.Customizations.Add(new ParentBuilder(random));
fixture.Customizations.Add(new ChildBuilder(random));

var actual = fixture.Create<Parent>();

Assert.True(0 < actual.Children.Count);
}

此测试通过,并使用自定义类 ParentBuilderChildBuilder :
public class ParentBuilder : ISpecimenBuilder
{
private readonly Random random;

public ParentBuilder(Random random)
{
this.random = random;
}

public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || t != typeof(Parent))
return new NoSpecimen();

if (this.random.Next(0, 2) == 0)
return context.Resolve(typeof(Mum));
else
return context.Resolve(typeof(Dad));
}
}

public class ChildBuilder : ISpecimenBuilder
{
private readonly Random random;

public ChildBuilder(Random random)
{
this.random = random;
}

public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || t != typeof(Child))
return new NoSpecimen();

if (this.random.Next(0, 2) == 0)
return context.Resolve(typeof(Son));
else
return context.Resolve(typeof(Daughter));
}
}

综上所述,如 you've previously discovered ,您正在插入 AutoFixture 的极限。它并不是真正设计用于处理像这里显示的那样的复杂递归对象设计。

关于abstract-class - AutoFixture 可以省略类层次结构之间的递归吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48438939/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com