【问题标题】:Customizing AutoFixture builder with seeded property使用种子属性自定义 AutoFixture 构建器
【发布时间】:2011-03-22 21:48:29
【问题描述】:

我有一个定制的 autofixture builder 用于集成测试。代码如下。

问题 1 - 目前第一笔交易的 TransactionViewKey.TransactionId 为 1 等。如何设置 TransactionViewKey TransactionId 使其从方法参数 beginningTransactionId 中播种?例如返回一个 TransactionViews 数组,其中第一个 TransactionId 为 200,然后每个递增 1?

问题 2 - 用于确定 transactiondate 的 lambda 似乎只运行一次 - 因此每个日期都是相同的值。如何设置构建器,以便它为每个生成的实例运行随机日期生成器,而不是只运行一次?

谢谢

  static TransactionView[] CreateTransactions(int transactionsToReturnCount, long beginningTransactionId) {
      Random random = new Random();
      IFixture fixture = new Fixture();
      fixture.Customize<TransactionViewKey>(ob => ob
                                    .With(t => t.TransactionId)
                                    .With(t => t.TransactionIdSpecified, true)
                                    .OmitAutoProperties()
                                    );
      fixture.Customize<TransactionView>(ob => ob
                                             .With(t => t.TransactionDate, DateTime.Now - new TimeSpan(random.Next(30),0,0,0))
                                             .With(t => t.PostDate, DateTime.Now - new TimeSpan(random.Next(30), 0, 0, 0))
                                             .With(t => t.ViewKey)
                                             .With(t => t.Amount)
                                             .OmitAutoProperties()
          );
      IEnumerable<TransactionView> transactionViews = fixture.CreateMany<TransactionView>(transactionsToReturnCount);
      return transactionViews.OrderBy(t => t.TransactionDate).ToArray();
  }

【问题讨论】:

    标签: c# autofixture


    【解决方案1】:

    在我深入回答具体问题之前,我想指出一些可能会容易得多的事情:您可能考虑在调用 CreateMany 之后将值分配给那些可写属性,但是在返回结果之前。

    类似这样的:

    var transactionViews = fixture.CreateMany<TransactionView>(transactionsToReturnCount);
    foreach (var tv in transactionViews)
    {
        tv.ViewKey.TransactionId = beginningTransactionId++;
        tv.TransactionDate = DateTime.Now - new TimeSpan(random.Next(30),0,0,0);
    }
    return transactionViews.OrderBy(t => t.TransactionDate).ToArray();
    

    这可能看起来像一个 hack,但实际上并非如此。 AutoFixture 旨在创建 Anonymous Values,因此,无论何时您尝试分配特定值(您目前的情况),您都超出了其最初的目的。

    不要误会我的意思:像这样使用 AutoFixture 很酷。我有时还必须为我用 AutoFixture 创建的样本的某些成员分配一些特定的值,但我倾向于使用上述技术,因为 getter 和 setter 的普通 .NET API 已经专门用于做到这一点。另一方面,AutoFixture 专门用于定义模糊规则,因此其目的恰恰相反。

    不过,我现在将回答上面提出的具体问题:

    问题 1

    我没有尝试编译这个,所以你可能需要稍微调整一下,但你能做的最好的事情是这样的:

    fixture.Customize<TransactionViewKey>(ob => ob
        .Without(t => t.TransactionId)
        .Do(t => t.TransactionId = beginningTransactionId++)
        .With(t => t.TransactionIdSpecified, true)
        .OmitAutoProperties());
    

    问题 2

    With 方法的第二个参数不是委托 - 它是一个,因此它只被评估一次。

    要每次评估它,您可以使用与上述相同的技巧:

    fixture.Customize<TransactionView>(ob => ob
        .Without(t => t.TransactionDate)
        .Do(t => t.TransactionDate = DateTime.Now - new TimeSpan(random.Next(30),0,0,0))
        .With(t => t.PostDate, DateTime.Now - new TimeSpan(random.Next(30), 0, 0, 0))
        .With(t => t.ViewKey)
        .With(t => t.Amount)
        .OmitAutoProperties());
    

    如果您有任何其他问题,请告诉我。

    HTH

    【讨论】:

    • 非常好,说得通 - 非常感谢。我没有意识到 Do 本质上是按对象构建运行的。从 autofixture 中获得很多好处 - 真希望我早点找到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多