You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用AutoFixture自定义含Usage集合的Report测试数据?

使用AutoFixture生成符合要求的Report实例

定义的实体类

internal sealed class Report
{
    public string Name { get; set; }
    public List<Usage> Usage { get; set; }
}

internal sealed class Usage
{
    public DateTime DateTime { get; set; }
    public int Count { get; set; }
}

需求说明

  • 生成多组Report实例
  • 每个Report包含15到30个Usage对象
  • 每个Usage的DateTime为过去30天内的不同日期

解决方案

方案1:直接定制Report生成逻辑(快速实现)

通过Fixture.Customize方法直接定义Report的Usage集合生成规则,适合简单场景:

var fixture = new Fixture();
var random = new Random();

// 定制Report的Usage集合生成逻辑
fixture.Customize<Report>(composer => composer
    .With(r => r.Usage, () => 
    {
        // 随机生成15-30之间的Usage数量
        var usageCount = random.Next(15, 31);
        // 生成过去30天的连续日期(含今天)
        var startDate = DateTime.Today.AddDays(-29);
        // 取对应数量的日期并打乱顺序,保证不重复
        var uniqueDates = Enumerable.Range(0, usageCount)
            .Select(i => startDate.AddDays(i))
            .OrderBy(_ => random.Next())
            .ToList();
        
        // 为每个日期生成Usage实例,Count由AutoFixture自动填充
        return uniqueDates.Select(date => 
            fixture.Build<Usage>().With(u => u.DateTime, date).Create())
            .ToList();
    }));

// 生成10个Report实例(可按需调整数量)
var reports = fixture.CreateMany<Report>(10).ToList();

方案2:自定义ISpecimenBuilder(适合复杂对象图)

如果实际对象结构更复杂,推荐用ISpecimenBuilder封装定制逻辑,避免代码耦合,同时保留AutoFixture对其他属性的自动生成能力:

自定义Builder类

public class ReportUsageSpecimenBuilder : ISpecimenBuilder
{
    private readonly Random _random = new Random();

    public object Create(object request, ISpecimenContext context)
    {
        // 仅处理Report类的Usage属性
        var propertyInfo = request as PropertyInfo;
        if (propertyInfo?.DeclaringType == typeof(Report) && propertyInfo.Name == nameof(Report.Usage))
        {
            var usageCount = _random.Next(15, 31);
            var startDate = DateTime.Today.AddDays(-29);
            var uniqueDates = Enumerable.Range(0, usageCount)
                .Select(i => startDate.AddDays(i))
                .OrderBy(_ => _random.Next())
                .ToList();

            // 通过AutoFixture生成Usage实例,仅替换DateTime属性
            return uniqueDates.Select(date =>
            {
                var usage = context.Resolve<Usage>() as Usage;
                usage.DateTime = date;
                return usage;
            }).ToList();
        }

        // 非目标请求,返回NoSpecimen让AutoFixture默认处理
        return new NoSpecimen();
    }
}

使用Builder

var fixture = new Fixture();
// 添加自定义Builder到Fixture的定制链中
fixture.Customizations.Add(new ReportUsageSpecimenBuilder());

// 生成多组Report实例
var reports = fixture.CreateMany<Report>(10).ToList();

关键细节说明

  • 日期唯一性:通过生成连续日期再打乱的方式保证不重复,若需要包含时间部分,可调整startDate为DateTime.Now.AddDays(-29),并确保每个时间点唯一
  • 随机数可控:若需要测试稳定性,可给Random指定固定种子(如new Random(42))
  • 扩展性:方案2的Builder模式可轻松扩展,比如后续需要调整日期范围、Usage数量区间,只需修改Builder内部逻辑即可

内容的提问来源于stack exchange,提问作者Complexity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:25:38