使用种子属性自定义 AutoFixture 构建器

发布于 2024-10-26 13:15:18 字数 1622 浏览 5 评论 0原文

我有一个用于集成测试的定制自动夹具构建器。代码如下。

问题 1 - 目前第一个事务的 TransactionViewKey.TransactionId 为 1 等。如何设置 TransactionViewKey TransactionId 以便它从方法参数 beginningTransactionId 中播种?例如,返回一个 TransactionView 数组,其中第一个 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();
  }

I've got a customized autofixture builder for an integration test. Code is below.

Question 1 - At present the first transaction has a TransactionViewKey.TransactionId of 1, etc. How do I set the TransactionViewKey TransactionId so it is seeded from the method param beginningTransactionId? eg returning an array of TransactionViews where the first TransactionId is 200, then each incrementing by 1?

Question 2 - the lambda for determining transactiondate seems to be run once only - and so each date is the same value. How do I setup the builder so it runs the random date generator for each generated instance rather than once only?

thanks

  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();
  }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

百变从容 2024-11-02 13:15:20

在我深入回答具体问题之前,我想指出一些可能更容易的事情:您可能考虑在调用 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();

这可能看起来像黑客,但实际上并非如此。 AutoFixture 旨在创建匿名值,因此无论何时您尝试分配特定的值(您当前的值),您就超出了其最初的目的。

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

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

问题 1

我还没有尝试编译它,所以您可能需要稍微调整一下,但最好的办法是do 会是这样的:

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());

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

华泰

Before I dive into answering the specific questions, I'd like to point out something that might be a lot easier: you might consider just assigning values to those writable properties after you called CreateMany, but before you return the result.

Something like this:

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();

This might look like a hack, but really isn't. AutoFixture is designed to create Anonymous Values so whenever you are trying to assign specific values (which you currently are), you are stepping outside of its original purpose.

Don't get me wrong: it's cool that you use AutoFixture like this. I also sometimes have to assign some specific values to some members of the specimens I have AutoFixture create, but I tend to use the above technique, because the normal .NET API of getters and setter is already specialized at doing exactly that. AutoFixture, on the other hand, is specialized at defining rules for being vague, so its purpose is the opposite.

That said, however, I will now answer the specific questions put forth above:

Question 1

I haven't tried to compile this, so you may have to tweak it a bit, but the best thing you can do would be something like this:

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

Question 2

The second parameter to the With method is not a delegate - it's a value so it's only being evaluated once.

To evaluate it each time, you can use the same trick as above:

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());

Please let me know if you have any additional questions.

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文