gpt4 book ai didi

autofixture - 如何将自定义 ISpecimenBuilders 与 OmitOnRecursionBehavior 结合使用?

转载 作者:行者123 更新时间:2023-12-04 14:59:38 26 4
gpt4 key购买 nike

我如何使用自定义 ISpecimenBuilder实例以及 OmitOnRecursionBehavior我想将其全局应用于所有夹具创建的对象?

我正在使用带有恶臭循环引用的 EF Code First 模型,就本问题而言,该模型无法消除:

public class Parent {
public string Name { get; set; }
public int Age { get; set; }
public virtual Child Child { get; set; }
}

public class Child {
public string Name { get; set; }
public int Age { get; set; }
public virtual Parent Parent { get; set; }
}

我熟悉侧步循环引用的技术,就像在这个通过测试中一样:

[Theory, AutoData]
public void CanCreatePatientGraphWithAutoFixtureManually(Fixture fixture)
{
//fixture.Customizations.Add(new ParentSpecimenBuilder());
//fixture.Customizations.Add(new ChildSpecimenBuilder());
fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
fixture.Behaviors.Add(new TracingBehavior());
var parent = fixture.Create<Parent>();
parent.Should().NotBeNull();
parent.Child.Should().NotBeNull();
parent.Child.Parent.Should().BeNull();
}

但是如果其中一个/两个自定义都没有注释,我会得到一个异常(exception):

System.InvalidCastException: Unable to cast object of type
'Ploeh.AutoFixture.Kernel.OmitSpecimen' to type 'CircularReference.Parent'.

失败的转换发生在我的 ISpecimenBuilder 中当我调用 ISpecimenContext 时的实现(显示在这个问题的底部)解决 Parent并且请求来自 Child正在解决。我可以防范来自 Child 的请求解决这样的操作:

//...
&& propertyInfo.ReflectedType != typeof(Child)
//...

但是,这似乎污染了 ISpecimenBuilder在知道“谁”可能提出请求的情况下执行。此外,它似乎重复了“全局” OmitOnRecursionBehavior 的工作。是为了做。

我想用 ISpecimenBuilder实例,因为除了处理循环引用之外,我还有其他事情要自定义。我花了很多时间在 SO 和 Ploeh 上寻找这样的场景的例子。但我还没有找到任何讨论 的内容行为和自定义的组合 .解决方案必须是我可以用 ICustomization 封装的解决方案,这一点很重要。 , 而不是测试设置中的线条和线条

//...
fixture.ActLikeThis(new SpecialBehavior())
.WhenGiven(typeof (Parent))
.AndDoNotEvenThinkAboutBuilding(typeof(Child))
.UnlessParentIsNull()
//...

...因为最终我想扩展一个 [AutoData]测试的属性。

以下是我的 ISpecimenBuilder TracingBehavior 的实现和输出对于失败的测试:

public class ChildSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
return propertyInfo != null
&& propertyInfo.PropertyType == typeof(Child)
? Resolve(context)
: new NoSpecimen(request);
}

private static object Resolve(ISpecimenContext context)
{
var child = (Child) context.Resolve(typeof (Child));
child.Name = context.Resolve(typeof (string)).ToString().ToLowerInvariant();
child.Age = Math.Min(17, (int) context.Resolve(typeof (int)));
return child;
}
}

public class ParentSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
return propertyInfo != null
&& propertyInfo.PropertyType == typeof (Parent)
? Resolve(context)
: new NoSpecimen(request);
}

private static object Resolve(ISpecimenContext context)
{
var parent = (Parent) context.Resolve(typeof (Parent));
parent.Name = context.Resolve(typeof (string)).ToString().ToUpperInvariant();
parent.Age = Math.Max(18, (int) context.Resolve(typeof (int)));
return parent;
}
}

CanCreatePatientGraphWithAutoFixtureManually(fixture: Ploeh.AutoFixture.Fixture) : Failed Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: CircularReference.Parent
Requested: System.String Name
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.String
Created: 38ab48f4-b071-40f0-b713-ef9d4c825a85
Created: Name38ab48f4-b071-40f0-b713-ef9d4c825a85
Created: Name38ab48f4-b071-40f0-b713-ef9d4c825a85
Requested: Int32 Age
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 9
Created: 9
Created: 9
Requested: CircularReference.Child Child
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: CircularReference.Child
Requested: System.String Name
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.String
Created: 1f5ca160-b211-4f82-871f-11882dbcf00d
Created: Name1f5ca160-b211-4f82-871f-11882dbcf00d
Created: Name1f5ca160-b211-4f82-871f-11882dbcf00d
Requested: Int32 Age
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 120
Created: 120
Created: 120
Requested: CircularReference.Parent Parent
Requested: CircularReference.Parent
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen

System.InvalidCastException: Unable to cast object of type 'Ploeh.AutoFixture.Kernel.OmitSpecimen' to type 'CircularReference.Parent'.

最佳答案

是否可以使用 Customize 自定义创建算法?方法?

如果是,您可以创建并使用以下 [ParentChildConventions]属性:

internal class ParentChildConventionsAttribute : AutoDataAttribute
{
internal ParentChildConventionsAttribute()
: base(new Fixture().Customize(new ParentChildCustomization()))
{
}
}

internal class ParentChildCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Child>(c => c
.With(x => x.Name,
fixture.Create<string>().ToLowerInvariant())
.With(x => x.Age,
Math.Min(17, fixture.Create<int>()))
.Without(x => x.Parent));

fixture.Customize<Parent>(c => c
.With(x => x.Name,
fixture.Create<string>().ToUpperInvariant())
.With(x => x.Age,
Math.Min(18, fixture.Create<int>())));
}
}

原始测试,使用 [ParentChildConventions]属性,通过:
[Theory, ParentChildConventions]
public void CanCreatePatientGraphWithAutoFixtureManually(
Parent parent)
{
parent.Should().NotBeNull();
parent.Child.Should().NotBeNull();
parent.Child.Parent.Should().BeNull();
}

关于autofixture - 如何将自定义 ISpecimenBuilders 与 OmitOnRecursionBehavior 结合使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18598719/

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