【问题标题】:Use value of a parent property when creating a complex child in AutoFixture在 AutoFixture 中创建复杂子项时使用父属性的值
【发布时间】:2011-09-06 12:32:40
【问题描述】:

我正在使用 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,但也没有设法解决它。

【问题讨论】:

    标签: c# autofixture


    【解决方案1】:

    AutoFixture 是基于一组规则和关于它可能被要求使用的 API 的假设。考虑到它是在没有任何 Child 和 Parent 类或给定 API 中的任何其他类型的先验知识的情况下创建和编译的。它只需要使用公共 API。

    将 AutoFixture 视为一个非常笨拙的程序员,甚至不懂您的语言(甚至不懂英语)。您可以使您的 API 越多fool-proof,使用 AutoFixture 就越容易。

    像这里描述的父/子关系这样的循环引用的问题是它破坏了封装。您需要至少创建一个最初处于无效状态的类实例。 AutoFixture 很难与这样的 API 一起工作,这主要应该被视为 API 可能会从重构中受益的警告信号。

    此外,.NET Framework 设计指南建议不要将数组公开为属性 - 特别是可写属性。因此,通过更好的封装设计,API 可能更容易使用,对 AutoFixture 以及您自己和您的同事来说都是如此。

    考虑到上面的 API,我看不出有什么方法可以使它更容易使用。考虑如何去掉循环引用,将集合属性设为只读,这样会容易很多。

    作为记录,我已经多年没有写过一个带有循环引用的 API,所以很有可能避免那些父/子关系。

    【讨论】:

    • 感谢您的回复马克!我完全同意你关于 API 的设计。不幸的是,在这种情况下,我无法影响 API 的设计方式,我只能使用它。无论如何,我可能会继续使用 AutoFixture,因为尽管我们的 API 很繁琐,但它让事情变得更容易。
    • 好吧,如果你总是像你的例子一样创建Parent 实例,你总是可以用Customize 方法封装这种行为......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多