当前位置: 首页 > news >正文

.NET单元测试使用AutoFixture按需填充的方法总结

AutoFixture是一个.NET库,旨在简化单元测试中的数据设置过程。通过自动生成测试数据,它帮助开发者减少测试代码的编写量,使得单元测试更加简洁、易读和易维护。AutoFixture可以用于任何.NET测试框架,如xUnit、NUnit或MSTest。

默认情况下AutoFixture生成的字段值很多时候都满足不了测试需求,比如:

public class User
{public int Id { get; set; }public string Name { get; set; } = null!;[EmailAddress]public string? Email { get; set; }[StringLength(512)]public string? Address { get; set; }public DateTime CreatedAt { get; set; } = DateTime.Now;
}

如果直接使用 Create<T>()生成的User对象,他会默认给你填充Id为随机整数,Name和Email为一串Guid,显然这里的邮箱地址生成就不能满足要求,并不是一个有效的邮箱格式

那么如何让AutoFixture按需生成有效的测试数据呢?方法其实有好几种:

一、直接定制

var fixture = new Fixture();
fixture.Customize<User>(c => c.With(x => x.Email, "特定值").Without(x => x.Id));

这里,With方法用于指定属性的具体值,而Without方法用于排除某些属性不被自动填充。

二、使用匿名函数

这在需要对生成的数据进行更复杂的操作时非常有用。

var fixture = new Fixture();
fixture.Customize<User>(c => c.FromFactory(() => new User
{Email = "通过工厂方法生成",
}));

三、实现ICustomization接口

对于更复杂的定制需求,可以通过实现ICustomization接口来创建一个定制化类。这种方法的好处是可以重用定制逻辑,并且使得测试代码更加整洁。

public class MyCustomClassCustomization : ICustomization
{public void Customize(IFixture fixture){fixture.Customize<User>(c => c.With(x => x.Email, "自定义值").Without(x => x.Id));}
}
// 使用定制化
var fixture = new Fixture();
fixture.Customize(new MyCustomClassCustomization());

四、使用Build<T>方法

Build<T>方法提供了一种链式调用的方式来定制类型的生成规则,这在只需要对单个对象进行简单定制时非常方便。

var myCustomObject = fixture.Build<User>().With(x => x.Email, $"{Guid.NewId()}@example.com").Without(x => x.Id).Create();

最佳实践

这里以xunit测试框架为例,我们需要提前引用AutoFixture,AutoFixture.Xunit2库,实现一个UserAutoDataAttribute类,继承自InlineAutoDataAttribute 重写GetData方法,大致代码如下:

public  class UserAutoDataAttribute : InlineAutoDataAttribute{public UserAutoDataAttribute(params object[] values) : base(values){ArgumentNullException.ThrowIfNull(values[0]);}public override IEnumerable<object[]> GetData(MethodInfo testMethod){var fixture = new Fixture();//这里使用上面的4种方式的一种,亦或者根据自身情况定制!var user = fixture.Build<User>()//.With(x => x.Id, 0).Without(x => x.Id) //ID需要排除因为EFCore需要插入时自动生成.With(x => x.Email, $"{Uuid7.NewUuid7()}@example.com") //邮箱地址,需要照规则生成.Create();yield return new object[] { Values[0], user };}}

下面是一个测试用例,需要填充db和一个自动生成的User参数:

public class UnitOfWorkTests(ITestOutputHelper output)
{[Theory][UserAutoData(1)][UserAutoData(2)]public async Task MyUnitOfWorkTest(int db, User user){var services = new ServiceCollection();services.AddLogging();services.AddDbContext<TestDbContext>(options =>{options.UseInMemoryDatabase($"test-{db}");});services.AddUnitOfWork<TestDbContext>();var provider = services.BuildServiceProvider();var uow = provider.GetRequiredService<IUnitOfWork<TestDbContext>>();//add userawait uow.GetRepository<User>().InsertAsync(user);await uow.SaveChangesAsync();// select uservar user2 = await uow.GetRepository<User>().FindAsync(1);Assert.NotNull(user2);// delete useruow.GetRepository<User>().Delete(1);var row = await uow.SaveChangesAsync();Assert.Equal(1, row);// select useruser2 = await uow.GetRepository<User>().GetFirstOrDefaultAsync(x => x.Id == 1);Assert.Null(user2);}
}

如果你已经习惯编写单元测试,但还没有使用AutoFixture,那么推荐你尝试一下。

相关文章:

  • VAE论文阅读
  • 2024中国大学生算法设计超级联赛(1)
  • 消费金融系统开发回忆录
  • 《昇思 25 天学习打卡营第 14 天 | 基于MindSpore的红酒分类实验 》
  • 代码解读:Diffusion Models中的长宽桶技术(Aspect Ratio Bucketing)
  • Android 15 之如何快速适配 16K Page Size
  • Spring Boot 学习(10)——固基(Idea 配置 git 访问 gitee)
  • JSON字符串介绍
  • 【深度学习图像】拼接图的切分
  • GIS技能应用(1)
  • Web前端:HTML篇(二)元素属性
  • SpringBoot缓存注解使用
  • 如何在Linux中打开core文件
  • 【手撕数据结构】拿捏单链表
  • 前后端分离项目部署,vue--nagix发布部署,.net--API发布部署。
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Akka系列(七):Actor持久化之Akka persistence
  • angular组件开发
  • Bytom交易说明(账户管理模式)
  • Computed property XXX was assigned to but it has no setter
  • FastReport在线报表设计器工作原理
  • Java深入 - 深入理解Java集合
  • PHP的类修饰符与访问修饰符
  • Spring-boot 启动时碰到的错误
  • storm drpc实例
  • 复杂数据处理
  • 计算机在识别图像时“看到”了什么?
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何进阶一名有竞争力的程序员?
  • 少走弯路,给Java 1~5 年程序员的建议
  • 十年未变!安全,谁之责?(下)
  • 探索 JS 中的模块化
  • 7行Python代码的人脸识别
  • 湖北分布式智能数据采集方法有哪些?
  • # include “ “ 和 # include < >两者的区别
  • # linux 中使用 visudo 命令,怎么保存退出?
  • ###C语言程序设计-----C语言学习(6)#
  • #etcd#安装时出错
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (day18) leetcode 204.计数质数
  • (el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (学习日记)2024.01.09
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)VC++中ondraw在什么时候调用的
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @开发者,一文搞懂什么是 C# 计时器!
  • [ IO.File ] FileSystemWatcher
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗
  • [CSS]一文掌握
  • [Enterprise Library]调用Enterprise Library时出现的错误事件之关闭办法