如何使用SemanticComparison比较两个匿名类型或两个不同类型的集合

时间:2015-09-30 05:14:51

标签: .net unit-testing xunit semantic-comparison

1。有没有一种简单的方法可以使用AutoFixture的SemanticComparison比较两种匿名类型?我目前的问题是我不能为第二个匿名对象构建Likeness。 简化示例:

var srcAnon = new { time = expectedTime, data = docsArray };
var resultAnon = new { time=actualTime, data = sutResponseArray };

var expectedAlike = srcAnon.AsSource()
            .OfLikeness<??WhatsHere??>()

2。我认为这个问题与第一个问题非常相关,因为他们都使用SemanticComparison来创建IEquatable实现。 In this question Mark Seemann使用MSTest断言和LINQ SequenceEqual方法提供了如何解决问题的答案。

这是否可以在类似场景中使用XUnit2断言库? XUnit支持Assert.Equal()用于相同类型的集合,它可以用于不同类型的集合,但是如果元素实现IEquatable(使用Likeness)。这样的事情(这不起作为resultallLikeness有不同的类型):

Assert.Equal(allLikeness.ToArray(),result.ToArray());

1 个答案:

答案 0 :(得分:3)

独立于任何单元测试框架,您始终可以下拉到the SequenceEquals<object> overload that also takes a comparer。这将使您能够比较完全不同的列表。这个测试展示了你如何欺骗&#39; .NET进入&#39;思考&#39;这两个异构数组是相同的:

[Fact]
public void TestDisparateSequences()
{
    var ints = new[] { 1, 3, 5, 7 };
    var strings = new[] { "foo", "bar", "baz", "qux" };

    Assert.True(
        ints.Cast<object>().SequenceEqual(
            strings.Cast<object>(),
            new TrueComparer<object>()),
        "Arrays look like they are equal.");
}

private class TrueComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T x, T y)
    {
        return true;
    }

    public int GetHashCode(T obj)
    {
        return 0;
    }
}

此测试通过,因为TrueComparer始终返回true。

显然,这不是特别实用,但它指出了可用于比较异构序列的相关构建块。

SemantiComparison提供了一个实现SemanticComparer<T>的{​​{1}}类,但它只适用于相同类型的值。因此,为了使用它来比较异构序列,您需要将其中一个列表映射到另一个类型的序列中。

通常情况下,你已经有了这样的地图,但如果没有,那么建立一个地图就是一个很好的动力。否则,您可以使用像AutoMapper这样的语义映射器。

举个例子,假设您有一个IEqualityComparer<T>类,如下所示:

Foo

和另一个public class Foo { public int Number { get; set; } public string Text { get; set; } } 类,非常相似:

Bar

您现在可以使用地图和public class Bar { public int Number { get; set; } public string Text { get; set; } }

比较foos和bar
SemanticComparison<Bar>

如果你给对象结构平等,它会让你的生活变得更轻松。这个答案只勾勒出可能的内容,而不是推荐的内容。