如何使用FluentAssertions比较DateOnly与DateTime类型?
问题描述
以下是简化后的测试代码:
record Type1(DateOnly Date); record Type2(DateTime Date); [Fact] public void Whatever() { var type1s = new[] { new Type1(DateOnly.Parse("2024-06-01")), new Type1(DateOnly.Parse("2024-07-01")) }; var type2s = new[] { new Type2(DateTime.Parse("2024-06-01")), new Type2(DateTime.Parse("2024-07-01")) }; type1s.Should().BeEquivalentTo(type2s); }
执行测试后失败,报错信息如下:
期望属性type1s[0].Date的值为<2024-06-01>,但实际为<2024-06-01>。
期望属性type1s[1].Date的值为<2024-07-01>,但实际为<2024-07-01>。
需要配置FluentAssertions使其能正确比较DateTime与DateOnly类型。
解决方案
方法1:局部等价性配置
在BeEquivalentTo方法中传入自定义配置,指定两种类型的转换比较规则:
type1s.Should().BeEquivalentTo(type2s, options => options // 当期望类型是DateTime、实际是DateOnly时,将DateTime转成DateOnly比较 .Using<DateOnly>(ctx => ctx.Subject.Should().Be(DateOnly.FromDateTime(ctx.Expectation))) .WhenTypeIs<DateTime>() // 当期望类型是DateOnly、实际是DateTime时,将DateOnly转成DateTime(时间取最小)比较 .Using<DateTime>(ctx => ctx.Subject.Should().Be(ctx.Expectation.ToDateTime(TimeOnly.MinValue))) .WhenTypeIs<DateOnly>());
方法2:全局配置(项目级生效)
如果多个测试需要统一的类型比较规则,可在测试项目初始化代码中注册全局配置:
FluentAssertions.AssertionOptions.AssertEquivalencyUsing(options => options .Using<DateOnly>(ctx => ctx.Subject.Should().Be(DateOnly.FromDateTime(ctx.Expectation))) .WhenTypeIs<DateTime>() .Using<DateTime>(ctx => ctx.Subject.Should().Be(ctx.Expectation.ToDateTime(TimeOnly.MinValue))) .WhenTypeIs<DateOnly>());
配置完成后,所有使用BeEquivalentTo的测试都会自动应用该转换规则。
方法3:自定义比较器
实现自定义相等比较器,再在配置中引用:
public class DateOnlyDateTimeComparer : IEqualityComparer { public new bool Equals(object x, object y) { if (x is DateOnly dateOnly && y is DateTime dateTime) { return dateOnly.Equals(DateOnly.FromDateTime(dateTime)); } if (x is DateTime dt && y is DateOnly do_) { return DateOnly.FromDateTime(dt).Equals(do_); } return EqualityComparer<object>.Default.Equals(x, y); } public int GetHashCode(object obj) { return obj?.GetHashCode() ?? 0; } }
测试中使用该比较器:
type1s.Should().BeEquivalentTo(type2s, options => options .Using(new DateOnlyDateTimeComparer()) .WhenTypeIs<DateOnly>() .Using(new DateOnlyDateTimeComparer()) .WhenTypeIs<DateTime>());
内容的提问来源于stack exchange,提问作者mnj
相关产品推荐
相关产品推荐

