【问题标题】:Using FluentAssertions to compare two collections of dictionaries that are containing different types使用 FluentAssertions 比较包含不同类型的两个字典集合
【发布时间】:2018-09-25 19:08:08
【问题描述】:

从我们的数据库中,我们查询放入ExpandoObject 类型的动态对象集合中的记录集,这些对象在字段上实现IDictionary<string, object>。这些是实际值。

从我们的 SpecFlow BDD 测试中,我们获得了实现 IDictionary<string, string> 的 TableRows 集合。这些是我们的预期值。

使用 FluentAssertions,我们希望使用 actual.Should().BeEquivalentTo(expected) 测试整个集合的等效性。不幸的是,这不起作用,因为当实际值不是 string 类型时,类型不匹配。

我们可以使用actual.Should().BeEquivalentTo(expected, options => options.WithAutoConversion()),但这会使整个实际集合成为IDictionary<string, string> 的集合,这对于比较日期没有用处。

我组装了一个会显示相同问题的测试用例:

var expected = new List<Dictionary<string, string>>();
expected.Add(new Dictionary<string, string>
{
    {"Name", "Moon Inc."},
    {"Number", "42"},
    {"Date", "2018-12-31"}
});

var actual = new List<ExpandoObject>();
dynamic eo = new ExpandoObject();
eo.Name = "Moon Inc.";
eo.Number = 42;
eo.Date = new DateTime(2018, 12, 31);

actual.Add(eo);

actual.Should().BeEquivalentTo(expected, options => options);
/* 
    This throws:
    NUnit.Framework.AssertionException: 
    Expected item[0][Number] to be System.String, but found System.Int32.
    Expected item[0][Date] to be System.String, but found System.DateTime.
*/

actual.Should().BeEquivalentTo(expected, options => options.WithAutoConversion());
/*
    This throws:
    NUnit.Framework.AssertionException: 
    Expected item[0][Date] to be "2018-12-31" with a length of 10, 
    but "31-12-2018 0:00:00" has a length of 18.
/*

我尝试在使用方法中使接收类型动态化,例如:

actual.Should().BeEquivalentTo(expected, options => options
    .Using<dynamic>(ctx => ctx.Subject.Should().Be(ctx.Expectation)).WhenTypeIs<DateTime>()
    .Using<dynamic>(ctx => ctx.Subject.Should().Be(ctx.Expectation)).WhenTypeIs<int>());

/* 
    NUnit.Framework.AssertionException: 
    Expected item[0][Number] to be System.String, but found System.Int32.
    Expected item[0][Date] to be System.String, but found System.DateTime.
*/

将双方解析为DateTime 并使用自动转换也不起作用,因为actual 类型不被视为DateTime,而是string

actual.Should().BeEquivalentTo(expected, options => options
    .Using<dynamic>(
        ctx =>
            DateTime.ParseExact(ctx.Subject, "yyy-MM-dd", CultureInfo.InvariantCulture)
            .Should().Be(DateTime.ParseExact(ctx.Expectation, "yyy-MM-dd", CultureInfo.InvariantCulture)))
    .WhenTypeIs<DateTime>()
    .WithAutoConversion());

/*
    NUnit.Framework.AssertionException: 
    Expected item[0][Date] to be "2018-12-31" with a length of 10, 
    but "31-12-2018 0:00:00" has a length of 18.
*/

FluentAssertions 有什么方法可以实现这一点吗?

【问题讨论】:

    标签: c# unit-testing fluent-assertions


    【解决方案1】:

    如果没有其他帮助,您可以像这样实现自定义IEquivalencyStep

    class WeakDateEquivalencyStep : IEquivalencyStep {
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) {
            if (context.IsRoot)
                return false;
            // handles situations when subject is date
            // but expectation is string
            return context.Subject is DateTime && context.Expectation is string;
        }
    
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) {
            DateTime exp;
            // we know that expection is string here
            if (!DateTime.TryParse((string) context.Expectation, CultureInfo.InvariantCulture, DateTimeStyles.None, out exp)) {
                // do something, your spec is invalid
                throw new Exception($"Value {context.Expectation} does not represent valid date time");
            }
    
            context.Subject.Should().Be(exp, context.Because, context.BecauseArgs);
            return true;
        }
    }
    

    然后

    actual.Should().BeEquivalentTo(expected, options => 
       options.Using(new WeakDateEquivalencyStep()).WithAutoConversion());
    

    【讨论】:

    • 这非常适合我的情况,有了这些知识,我也可以将它扩展到其他类型。非常感谢!
    猜你喜欢
    • 2014-11-12
    • 1970-01-01
    • 2021-06-02
    • 2020-01-20
    • 2019-07-14
    • 2021-10-08
    • 2012-05-10
    • 1970-01-01
    • 2019-09-17
    相关资源
    最近更新 更多