一款开源、强大、简单易用的 .NET 假数据生成利器

前言

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

项目介绍

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

支持语言

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

应用场景

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

支持以下语言环境

Bogus 支持以下语言环境:

创建一个 .NET 控制台应用

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

项目 NuGet 安装

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

复制代码
Install-Package Bogus

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

Bogus 快速入门

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

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

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

        /// <summary>
        /// 生成随机订单的模拟用户
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public static List<User> GenerateSampleUsers(int count = 3)
        {
            // 设置随机种子,生成可重复的数据集
            Randomizer.Seed = new Random(3897234);

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

            var orderIds = 0;
            var testOrders = new Faker<Order>()
                // 开启严格模式:确保所有属性都有规则
                .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<User>()
                // 自定义构造函数
                .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<Gender>())
                .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);
        }
    }

    /// <summary>
    /// 订单实体
    /// </summary>
    public class Order
    {
        public int OrderId { get; set; }
        public string Item { get; set; }
        public int Quantity { get; set; }
        public int? LotNumber { get; set; }
    }

    /// <summary>
    /// 性别枚举
    /// </summary>
    public enum Gender
    {
        Male,
        Female
    }

    /// <summary>
    /// 用户实体
    /// </summary>
    public class User
    {
        public User(int userId, string ssn)
        {
            this.Id = userId;
            this.SSN = ssn;
        }

        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string SomethingUnique { get; set; }
        public Guid SomeGuid { get; set; }
        public string Avatar { get; set; }
        public Guid CartId { get; set; }
        public string SSN { get; set; }
        public Gender Gender { get; set; }
        public List<Order> Orders { get; set; }
    }

生成随机用户信息

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

csharp 复制代码
        /// <summary>
        /// 生成随机用户信息
        /// </summary>
        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 数据:

csharp 复制代码
    /// <summary>
    /// EF Core 数据库种子数据填充
    /// 适合开发/测试环境,在应用启动时自动填充数据:
    /// FakeData.Init(10); // 生成 10 个 Blog,每个包含 3~5 篇 Post
    /// </summary>
    public static class FakeData
    {
        public static List<Blog> Blogs = new List<Blog>();
        public static List<Post> Posts = new List<Post>();

        public static void Init(int count)
        {
            var postId = 1;
            var postFaker = new Faker<Post>()
                .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<Blog>()
                .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);
        }
    }

    /// <summary>
    /// Blog
    /// </summary>
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
        public List<Post> Posts { get; set; }
    }

    /// <summary>
    /// Post
    /// </summary>
    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int BlogId { get; set; }
    }

在 Program.cs 启动时填充:

ini 复制代码
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

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

            var app = builder.Build();

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

                // 确保数据库已创建
                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,添加自定义的数据生成器:

csharp 复制代码
    /// <summary>
    /// 为 Bogus 的 Faker 类提供食品相关的自定义假数据扩展方法
    /// </summary>
    public static class FoodExtensions
    {
        /// <summary>
        /// 生成一个随机的糖果名称
        /// </summary>
        /// <param name="faker"></param>
        /// <returns></returns>
        public static string Candy(this Faker faker)
        {
            return faker.PickRandom(new[] { "巧克力", "棒棒糖", "口香糖", "软糖", "太妃糖" });
        }

        /// <summary>
        /// 生成一个随机的饮品名称
        /// </summary>
        /// <param name="faker"></param>
        /// <returns></returns>
        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推荐或自荐(让优秀的项目和框架不被埋没🤞)。

相关推荐
阿祖zu22 分钟前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才31 分钟前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒38 分钟前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20231 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei1 小时前
controller注册及调用时机
后端
edwarddamon2 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈2 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1002 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师3 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言
DantyWei3 小时前
kube-controller-manager的leader选举流程和策略
后端