在 AutoFixture 中创建复杂子级时使用父级属性的值
我正在使用 AutoFixture 为涉及父对象和复杂子对象的结构生成数据,如下所示:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public Child[] Children { get; set; }
}
public class Child
{
public string Name { get; set; }
public int ParentId { get; set; }
}
有没有办法自动设置生成的 Child
的属性 ParentId
> 对象分配给父级的 id?现在我的解决方案看起来像这样,这不是很漂亮:
var parent = fixture.Build<Parent>().Without(p => p.Children).CreateAnonymous();
parent.Children = fixture.CreateMany<Child>(10).ToArray();
foreach (var i in parent.Children)
{
i.ParentId = parent.Id;
}
感觉好像有更好的方法来做到这一点,但我缺少什么?我考虑过创建一个自定义 ISpecimenBuilder
但也没有设法以这种方式解决它。
I'm using AutoFixture to generate data for a structure involving a parent object and complex child objects, like this:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public Child[] Children { get; set; }
}
public class Child
{
public string Name { get; set; }
public int ParentId { get; set; }
}
Is there a way to automatically set the property ParentId
of the generated Child
object to the id assigned to the parent? Right now my solution looks like this, which isn't very pretty:
var parent = fixture.Build<Parent>().Without(p => p.Children).CreateAnonymous();
parent.Children = fixture.CreateMany<Child>(10).ToArray();
foreach (var i in parent.Children)
{
i.ParentId = parent.Id;
}
It feels like there's a better way to do this that I am missing? I looked into creating a custom ISpecimenBuilder
but didn't manage to solve it that way either.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
AutoFixture 基于一组关于它可能需要使用的 API 的规则和假设。假设它是在事先不了解
Child
和Parent
类或给定 API 中的任何其他类型的情况下创建和编译的。它所需要使用的只是公共 API。将 AutoFixture 视为一个非常愚蠢的程序员,他甚至听不懂您的语言(甚至英语)。您的 API 越防呆,它就会越容易是与它一起使用AutoFixture。
像这里描述的父/子关系这样的循环引用的问题是它破坏了封装。您需要创建至少一个最初处于无效状态的类实例。 AutoFixture 很难与这样的 API 一起工作,这主要应该被视为一个警告信号,表明 API 可能会从重构中受益。
此外,.NET Framework 设计指南建议不要将数组公开为属性,尤其是可写属性。因此,通过更好的封装设计,对于 AutoFixture 以及您自己和您的同事来说,API 可能会更容易使用。
鉴于上面的 API,我看不出有任何方法可以使其更容易使用。考虑一下如何去掉循环引用,让集合属性只读,就会容易很多。
根据记录,我已经很多年没有编写带有循环引用的 API,因此很有可能避免这些父/子关系。
AutoFixture is based on a set of rules and assumptions about the API it may be asked to work with. Consider that it's been created and compiled without any prior knowledge of the
Child
andParent
classes, or any other types in a given API. All it has to work with is the public API.Think of AutoFixture as a very dim programmer who doesn't even understand your language (not even English). The more fool-proof you can make your API, the easier it will be to use AutoFixture with it.
The problem with circular references like the Parent/Child relationship described here is that it breaks encapsulation. You'll need to create at least one of the class instances initially in an invalid state. That it's difficult to make AutoFixture work with such an API should mainly be taken as a warning sign that the API might benefit from refactoring.
Additionally, the .NET Framework Design Guidelines recommends against exposing arrays as properties - particularly writable properties. Thus, with a better encapsulated design, the API might be much easier to work with, both for AutoFixture and yourself and your colleagues.
Given the API above, I don't see any way this can be made much easier to work with. Consider how to remove the circular reference and make collection properties read-only, and it will be much easier.
For the record, I haven't written an API with a circular reference for years, so it's quite possible to avoid those Parent/Child relations.