如何为特定类自定义 AutoFixture 行为 [英] How do I customize AutoFixture behaviours for specific classes
问题描述
我需要启用 AutoFixture 以创建具有循环引用的类型实例(来自第三方提供的 API).为此,我可以删除默认的 ThrowingRecursionBehavior
,如下所示:
I need to enable AutoFixture to create instances of types with circular references (from an API provided by a third party). To do this I can remove the default ThrowingRecursionBehavior
as shown below:
public class RecursiveObjectCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
}
}
但是,我知道当通过属性应用自定义时,这将删除所有类型的 ThrowingRecursionBehavior
.如何将修改后的行为限制为仅适用于特定类型?
However, I understand that this will remove the ThrowingRecursionBehavior
for all types when the customization is applied via an attribute. How can I limit the modified behavior to only apply to the specific types?
推荐答案
您必须为此创建自定义行为.
You'll have to create a custom behavior for that.
这里有一些开始:
public class OmitOnRecursionForRequestBehavior : ISpecimenBuilderTransformation
{
private const int DefaultRecursionDepth = 1;
private readonly int recursionDepth;
private readonly object request;
public OmitOnRecursionForRequestBehavior(object request)
: this(request, DefaultRecursionDepth)
{
}
public OmitOnRecursionForRequestBehavior(
object request,
int recursionDepth)
{
if (request == null)
throw new ArgumentNullException("request");
if (recursionDepth < 1)
throw new ArgumentOutOfRangeException(
"recursionDepth",
"Recursion depth must be greater than 0.");
this.recursionDepth = recursionDepth;
this.request = request;
}
public ISpecimenBuilder Transform(ISpecimenBuilder builder)
{
if (builder == null)
throw new ArgumentNullException("builder");
return new RecursionGuard(
builder,
new RecursionForRequestHandler(
request,
new OmitOnRecursionHandler(),
builder),
recursionDepth);
}
}
public class RecursionForRequestHandler : IRecursionHandler
{
private readonly object request;
private readonly IRecursionHandler handlerForRequest;
private readonly ISpecimenBuilder handler;
public RecursionForRequestHandler(
object request,
IRecursionHandler handlerForRequest,
ISpecimenBuilder handler)
{
if (request == null)
throw new ArgumentNullException("request");
if (handlerForRequest == null)
throw new ArgumentNullException("handlerForRequest");
if (handler == null)
throw new ArgumentNullException("handler");
this.request = request;
this.handlerForRequest = handlerForRequest;
this.handler = handler;
}
public object HandleRecursiveRequest(
object request,
IEnumerable<object> recordedRequests)
{
if (this.request.Equals(request))
return handlerForRequest.HandleRecursiveRequest(
request,
recordedRequests);
return handler.Create(request, new SpecimenContext(handler));
}
}
这是你将如何使用它:
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(MyType)));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(AnotherType)));
请注意,不要删除 ThrowingRecursionBehavior
,因为它将用于保护其他请求,否则将抛出 StackOverflowException
.
Note that you don't remove the ThrowingRecursionBehavior
as it will be used to guard the other requests, otherwise a StackOverflowException
will be thrown.
但是,如果您指定的 recursionDepth
大于 1,则必须删除 ThrowingRecursionBehavior
并创建一个具有更大或等于 recursionDepth 的自定义代码>.
However, if you specify a recursionDepth
greater than 1, you'll have to remove the ThrowingRecursionBehavior
and create a customized one with a greater or equal recursionDepth
.
public class DepthThrowingRecursionBehavior : ISpecimenBuilderTransformation
{
private readonly int recursionDepth;
public DepthThrowingRecursionBehavior(int recursionDepth)
{
if (recursionDepth < 1)
throw new ArgumentOutOfRangeException(
"recursionDepth",
"Recursion depth must be greater than 0.");
this.recursionDepth = recursionDepth;
}
public ISpecimenBuilder Transform(ISpecimenBuilder builder)
{
if (builder == null)
throw new ArgumentNullException("builder");
return new RecursionGuard(
builder,
new ThrowingRecursionHandler(),
recursionDepth);
}
}
fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new DepthThrowingRecursionBehavior(2));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(MyType), 2));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(AnotherType), 1));
这篇关于如何为特定类自定义 AutoFixture 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!