前言

在日常的 .NET 项目开发中,我们经常需要大量的测试数据来验证业务逻辑、填充数据库、进行性能测试或者做产品演示。手动编写这些测试数据不仅枯燥乏味、浪费时间,而且难以覆盖各种边界场景。今天大姚给大家推荐一款开源、强大、简单易用的 .NET 假数据生成库:Bogus

项目介绍

Bogus 是一个基于著名的 faker.js 移植而来的开源(MIT License) .NET 假数据生成库,它为 .NET 开发者提供了一套强大、简单易用的 API,可快速生成各种类型的模拟数据,支持 40+ 种语言区域本地化,广泛应用于单元测试、数据库填充、原型演示以及示例数据生成等场景。

支持语言

支持语言:C#、F#、VB.NET。

应用场景

  • 单元测试 / 集成测试:快速生成符合业务模型的测试对象,替代手工 Mock 数据。
  • 数据库填充(Seed):开发/测试环境数据库填充真实感十足的假数据。
  • 性能与压力测试:批量生成大规模数据集来模拟真实负载。
  • API 开发调试:快速构造 API 返回的模拟响应数据。
  • 数据脱敏:替换生产数据中的敏感信息。

支持以下语言环境

Bogus 支持以下语言环境:

image

创建一个 .NET 控制台应用

接下来我们创建一个名为:BogusExercise .NET 9 控制台应用:

image

image

项目 NuGet 安装

在 NuGet 包管理器控制台中执行:

Install-Package Bogus

或者在 NuGet 包管理器中搜索安装:

image

Bogus 快速入门

生成 3 个随机订单的模拟用户信息

以下是 Bogus 仓库中提供的示例代码,使用 Bogus 生成了 3 个带随机订单的模拟用户。

    public classProgram
    {
        static void Main(string[] args)
        {
            //生成 3 个随机订单的模拟用户信息
            var users = GenerateSampleUsers(3);
        }

        /// 
        /// 生成随机订单的模拟用户
        /// 

        /// 
        /// 
        public static List GenerateSampleUsers(int count = 3)
        {
            // 设置随机种子,生成可重复的数据集
            Randomizer.Seed = new Random(3897234);

            var fruit = new[] { "apple", "banana", "orange", "strawberry", "kiwi" };

            var orderIds = 0;
            var testOrders = new Faker()
                // 开启严格模式:确保所有属性都有规则
                .StrictMode(true)
                // OrderId 自增
                .RuleFor(o => o.OrderId, f => orderIds++)
                // 从水果篮中随机挑选
                .RuleFor(o => o.Item, f => f.PickRandom(fruit))
                // 随机数量 1~10
                .RuleFor(o => o.Quantity, f => f.Random.Number(1, 10))
                // 可空 int?,80% 概率为 null
                .RuleFor(o => o.LotNumber, f => f.Random.Int(0, 100).OrNull(f, .8f));

            var userIds = 0;
            var testUsers = new Faker()
                // 自定义构造函数
                .CustomInstantiator(f => new User(userIds++, f.Random.Replace("###-##-####")))
                // 基本规则
                .RuleFor(u => u.FirstName, f => f.Name.FirstName())
                .RuleFor(u => u.LastName, f => f.Name.LastName())
                .RuleFor(u => u.Avatar, f => f.Internet.Avatar())
                .RuleFor(u => u.UserName, (f, u) => f.Internet.UserName(u.FirstName, u.LastName))
                .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.FirstName, u.LastName))
                .RuleFor(u => u.SomethingUnique, f => $"Value {f.UniqueIndex}")
                .RuleFor(u => u.SomeGuid, Guid.NewGuid)
                // 随机选取枚举
                .RuleFor(u => u.Gender, f => f.PickRandom())
                .RuleFor(u => u.CartId, f => Guid.NewGuid())
                // 组合属性:利用已生成的 FirstName 和 LastName
                .RuleFor(u => u.FullName, (f, u) => u.FirstName + " " + u.LastName)
                // 嵌套集合生成
                .RuleFor(u => u.Orders, f => testOrders.Generate(3))
                // 生成完成后的回调
                .FinishWith((f, u) =>
                {
                    Console.WriteLine("User Created! Name={0}", u.FullName);
                });

            // 一次生成 3 个用户
            return testUsers.Generate(count);
        }
    }

    /// 
    /// 订单实体
    /// 

    publicclassOrder
    {
        publicint OrderId { get; set; }
        publicstring Item { get; set; }
        publicint Quantity { get; set; }
        publicint? LotNumber { get; set; }
    }

    /// 
    /// 性别枚举
    /// 

    publicenum Gender
    {
        Male,
        Female
    }

    /// 
    /// 用户实体
    /// 

    publicclassUser
    {
        public User(int userId, string ssn)
        {
            this.Id = userId;
            this.SSN = ssn;
        }

        publicint Id { get; set; }
        publicstring FirstName { get; set; }
        publicstring LastName { get; set; }
        publicstring FullName { get; set; }
        publicstring UserName { get; set; }
        publicstring Email { get; set; }
        publicstring SomethingUnique { get; set; }
        public Guid SomeGuid { get; set; }
        publicstring Avatar { get; set; }
        public Guid CartId { get; set; }
        publicstring SSN { get; set; }
        public Gender Gender { get; set; }
        public List Orders { get; set; }
    }

生成随机用户信息

使用 Bogus 快速生成随机用户姓名、邮箱、地址、电话等关联数据:

        /// 
        /// 生成随机用户信息
        /// 

        public static void GenerateRandomData()
        {
            // 自动生成姓名、邮箱、地址、电话等关联数据
            var faker = new Faker("zh_CN");// 使用简体中文
            var randomName = faker.Name.FullName();
            var randomEmail = faker.Internet.Email();
            var randomAddress = faker.Address.FullAddress();
            var randomPhone = faker.Phone.PhoneNumber();
            Console.WriteLine($"Name: {randomName}");
            Console.WriteLine($"Email: {randomEmail}");
            Console.WriteLine($"Address: {randomAddress}");
            Console.WriteLine($"Phone: {randomPhone}");
        }

EF Core 数据库种子数据填充

使用 EF Core 填充 Blog & Post 数据:

    /// 
    /// EF Core 数据库种子数据填充
    /// 适合开发/测试环境,在应用启动时自动填充数据:
    /// FakeData.Init(10); // 生成 10 个 Blog,每个包含 3~5 篇 Post
    /// 

    publicstaticclassFakeData
    {
        publicstatic List Blogs = new List();
        publicstatic List Posts = new List();

        public static void Init(int count)
        {
            var postId = 1;
            var postFaker = new Faker()
                .RuleFor(p => p.PostId, _ => postId++)
                .RuleFor(p => p.Title, f => f.Hacker.Phrase())
                .RuleFor(p => p.Content, f => f.Lorem.Sentence());

            var blogId = 1;
            var blogFaker = new Faker()
                .RuleFor(b => b.BlogId, _ => blogId++)
                .RuleFor(b => b.Url, f => f.Internet.Url())
                .RuleFor(b => b.Posts, (f, b) =>
                {
                    postFaker.RuleFor(p => p.BlogId, _ => b.BlogId);
                    var posts = postFaker.GenerateBetween(3, 5);

                    // 关键:收集所有 Posts 到静态列表中
                    Posts.AddRange(posts);

                    return posts;
                });

            // 清空旧数据,避免重复调用累积
            Blogs.Clear();
            Posts.Clear();

            Blogs = blogFaker.Generate(count);
        }
    }

    /// 
    /// Blog
    /// 

    publicclassBlog
    {
        publicint BlogId { get; set; }
        publicstring Url { get; set; }
        public List Posts { get; set; }
    }

    /// 
    /// Post
    /// 

    publicclassPost
    {
        publicint PostId { get; set; }
        publicstring Title { get; set; }
        publicstring Content { get; set; }
        publicint BlogId { get; set; }
    }

在 Program.cs 启动时填充:

    public classProgram
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // 注册 DbContext
            builder.Services.AddDbContext(options =>
                options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

            var app = builder.Build();

            // 应用启动时填充种子数据
            using (var scope = app.Services.CreateScope())
            {
                var context = scope.ServiceProvider.GetRequiredService();

                // 确保数据库已创建
                context.Database.EnsureCreated();

                // 仅在数据库为空时填充假数据
                if (!context.Blogs.Any())
                {
                    FakeData.Init(10); // 生成 10 个 Blog,每个包含 3~5 篇 Post

                    context.Blogs.AddRange(FakeData.Blogs);
                    context.Posts.AddRange(FakeData.Posts);
                    context.SaveChanges();

                    Console.WriteLine($"已填充 {FakeData.Blogs.Count} 个博客, {FakeData.Posts.Count} 篇文章");
                }
            }

            app.MapControllers();
            app.Run();
        }
    }

自定义扩展 Bogus 数据集

开发者可以轻松扩展 Bogus,添加自定义的数据生成器:

    /// 
    /// 为 Bogus 的 Faker 类提供食品相关的自定义假数据扩展方法
    /// 

    publicstaticclassFoodExtensions
    {
        /// 
        /// 生成一个随机的糖果名称
        /// 

        /// 
        /// 
        public static string Candy(this Faker faker)
        {
            return faker.PickRandom(new[] { "巧克力", "棒棒糖", "口香糖", "软糖", "太妃糖" });
        }

        /// 
        /// 生成一个随机的饮品名称
        /// 

        /// 
        /// 
        public static string Drink(this Faker faker)
        {
            return faker.PickRandom(new[] { "可乐", "雪碧", "橙汁", "咖啡", "牛奶" });
        }
    }
    
    // 使用自定义扩展
    var faker = new Faker();
    Console.WriteLine($"最爱糖果: {faker.Candy()}");
    Console.WriteLine($"最爱饮料: {faker.Drink()}");

项目源码地址

更多项目实用功能和特性欢迎前往项目开源地址查看👀,别忘了给项目一个Star支持💖。

优秀项目和框架精选

该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。

DotNetGuide技术社区

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

欢迎加入DotNetGuide技术社区微信交流群👪


原文地址: https://www.cveoy.top/t/topic/qFWf 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录