我一直在尝试对一些简单的不可变对象进行建模,其中我有两个构造函数重载:一个重载接受每个只读属性的参数,另一个接受其自身的实例进行克隆(以便在大多数属性时使用)值将与另一个实例的值相同)。
public class Parent {
public Parent(Child child, Pet pet) {
Child = child;
Pet = pet;
}
public Parent(Parent template) {
Child = template.Child;
Pet = template.Pet;
}
public Child Child { get; private set; }
public Pet Pet { get; private set; }
}
正如我所期望的,这个测试通过了:
[Theory]
[AutoData]
public void Properties_Equal_Constructor_Arguments(Child expectedChild, Pet expectedPet)
{
// act
var sut = new Parent(expectedChild, expectedPet);
// assert
sut.Child.Should().Be(expectedChild);
sut.Pet.Should().Be(expectedPet);
}
但这个测试抛出了一个Ploeh.AutoFixture.ObjectCreationException
,无法创建类型的实例System.Reflection.RuntimeParameterInfo
(使用 AutoData 参数),或键入Ploeh.AutoFixture.Kernel.SeededRequest
(不使用自动数据)(?!?)
[Theory]
[AutoData]
public void Properties_Equal_Properties_Of_Template_Constructor_Argument(Parent template)
{
// arrange
//var fixture = new Fixture(); // yields same error but for type
//var template = fixture.Create<Parent>();// Ploeh.AutoFixture.Kernel.SeededRequest
var expectedChild = template.Child;
var expectedPet = template.Pet;
// act
var sut = new Parent(template);
// assert
sut.Child.Should().Be(expectedChild);
sut.Pet.Should().Be(expectedPet);
}
首先,我在我的类中没有发现任何循环引用,就像您通常在有关此问题的问题中看到的那样,其中子对象具有对其父对象的属性引用(就像数据库实体建模有时会发生的情况一样)。其次,当我过去收到此错误时,它指的是对我的类中明确使用的类型的循环引用,与本例不同。
为什么会发生这种情况?
为了完整起见,以下是其他相关类和收到的完整错误消息:
public class Child {
public Child(string value) {
Value = value;
}
public string Value { get; private set; }
}
public class Pet {
public Pet(string name) {
Name = name;
}
public string Name { get; private set; }
}
System.InvalidOperationException 获取时抛出异常
理论数据
AutoFixtureTests.CircularReferenceTests.Properties_Equal_Properties_Of_Template_Constructor_Argument:
Ploeh.AutoFixture.ObjectCreationException:AutoFixture 无法
创建 System.Reflection.RuntimeParameterInfo 类型的实例
因为遍历的对象图包含循环引用。
有关圆形路径的信息如下。这是正确的
当 Fixture 配备 ThrowingRecursionBehavior 时的行为,
这是默认值。这可以确保您被告知
代码中的循环引用。你的第一反应应该是
重新设计您的 API 以消除所有循环引用。
但是,如果这是不可能的(很可能是因为部分或全部
该API由第三方提供),您可以替换此默认值
具有不同行为的行为:在 Fixture 实例上,删除
Fixture.Behaviors 中的 ThrowingRecursionBehavior,然后添加
OmitOnRecursionBehavior 的实例。小路:
AutoFixtureTests.Parent 模板 --> AutoFixtureTests.Parent -->
AutoFixtureTests.Parent 模板 -->
Ploeh.AutoFixture.Kernel.SeedRequest
在
Ploeh.AutoFixture.Kernel.ThrowingRecursionHandler.HandleRecursiveRequest(对象
请求,IEnumerable1 recordedRequests) at
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request,
ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.Postprocessor
1.创建(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,
ISpecimenContext 上下文)位于
System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() at
System.Collections.Generic.List
1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 个来源)位于
Ploeh.AutoFixture.Kernel.MethodInvoker.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.Postprocessor1.Create(Object request,
ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(Object request,
ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.TerminatingWithPathSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request,
ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object
request, ISpecimenContext context) at
Ploeh.AutoFixture.Kernel.Postprocessor
1.创建(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象
请求,ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,
ISpecimenContext 上下文)位于
Ploeh.AutoFixture.Xunit.AutoDataAttribute.GetData(MethodInfo
methodUnderTest,类型 [] 参数类型)位于
Xunit.Extensions.TheoryAttribute.d_7.MoveNext() 在
Xunit.Extensions.TheoryAttribute.EnumerateTestCommands(IMethodInfo
方法)在
Xunit.Extensions.TheoryAttribute.c_DisplayClass5.b__1()
在
Xunit.Extensions.TheoryAttribute.LambdaTestCommand.Execute(对象 testClass)
当不使用 AutoDataAttribute 时:
Ploeh.AutoFixture.ObjectCreationException AutoFixture 无法
创建 Ploeh.AutoFixture.Kernel.SeededRequest 类型的实例
因为遍历的对象图包含循环引用。
有关圆形路径的信息如下。这是正确的
当 Fixture 配备 ThrowingRecursionBehavior 时的行为,
这是默认值。这可以确保您被告知
代码中的循环引用。你的第一反应应该是
重新设计您的 API 以消除所有循环引用。
但是,如果这是不可能的(很可能是因为部分或全部
该API由第三方提供),您可以替换此默认值
具有不同行为的行为:在 Fixture 实例上,删除
Fixture.Behaviors 中的 ThrowingRecursionBehavior,然后添加
OmitOnRecursionBehavior 的实例。小路:
AutoFixtureTests.Parent 模板 --> AutoFixtureTests.Parent -->
AutoFixtureTests.Parent 位于
Ploeh.AutoFixture.Kernel.ThrowingRecursionHandler.HandleRecursiveRequest(对象请求,IEnumerable1 recordedRequests)
at
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.Postprocessor
1.Create(对象请求,ISpecimenContext上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.Postprocessor1.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.TerminatingWithPathSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at System.Linq.Enumerable.WhereSelectArrayIterator
2.MoveNext() 位于
System.Collections.Generic.List1..ctor(IEnumerable
1 个集合)
在 System.Linq.Enumerable.ToList(IEnumerable1 source) at
Ploeh.AutoFixture.Kernel.MethodInvoker.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at
Ploeh.AutoFixture.Kernel.Postprocessor
1.Create(对象请求,ISpecimenContext上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TracingBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.TerminateWithPathSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文)
在
Ploeh.AutoFixture.SpecimenFactory.Create(ISpecimenContext 上下文,T 种子)
在 Ploeh.AutoFixture.SpecimenFactory.Create(ISpecimenContext 上下文)
在
AutoFixtureTests.CircularReferenceTests.Properties_Equal_Properties_Of_Template_Constructor_Argument()
在 AutoFixtureTests.cs 中:第 28 行