如何使用 SemanticComparison 比较两个匿名类型或两个不同类型的集合
How to compare two anonymous types or two collection of different types using SemanticComparison
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)。像这样的东西(这不起作用,因为 result
和 allLikeness
有不同的类型):
Assert.Equal(allLikeness.ToArray(),result.ToArray());
独立于任何单元测试框架,您始终可以下降到 the SequenceEquals<object>
overload that also takes a comparer。这将使您能够比较完全不同的列表。该测试演示了如何将 .NET 'trick' 转换为 'thinking' 两个异构数组相同:
[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
始终 returns 为真。
显然,这不是特别实用,但它指出了可以用来比较异构序列的相关构建块。
SemantiComparison 提供了一个 SemanticComparer<T>
class 来实现 IEqualityComparer<T>
,但它只适用于相同类型的值。因此,为了使用它来比较异构序列,您需要将其中一个列表映射到另一种类型的序列中。
通常,您周围已经有了这样的地图,但如果没有,这也是构建地图的良好动力。否则,您可以使用像 AutoMapper.
这样的语义映射器
例如,假设您有一个 Foo
class 这样的:
public class Foo
{
public int Number { get; set; }
public string Text { get; set; }
}
和另一个Bar
class,非常相似:
public class Bar
{
public int Number { get; set; }
public string Text { get; set; }
}
您现在可以使用地图比较 foos 和 bars,并且 SemanticComparison<Bar>
:
[Fact]
public void TestEquivalentSequences()
{
var foos = new[]
{
new Foo { Number = 42, Text = "ploeh" },
new Foo { Number = 1337, Text = "fnaah" }
};
var bars = new[]
{
new Bar { Number = 42, Text = "ploeh" },
new Bar { Number = 1337, Text = "fnaah" }
};
AutoMapper.Mapper.CreateMap<Foo, Bar>();
Assert.True(
foos.Select(AutoMapper.Mapper.Map<Bar>).SequenceEqual(
bars,
new SemanticComparer<Bar>()),
"Mapped arrays should be equivalent.");
}
不过,如果你给你的对象结构平等,它会让你的生活变得更轻松。此答案仅勾勒出可能的内容,而不是推荐的内容。
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)。像这样的东西(这不起作用,因为 result
和 allLikeness
有不同的类型):
Assert.Equal(allLikeness.ToArray(),result.ToArray());
独立于任何单元测试框架,您始终可以下降到 the SequenceEquals<object>
overload that also takes a comparer。这将使您能够比较完全不同的列表。该测试演示了如何将 .NET 'trick' 转换为 'thinking' 两个异构数组相同:
[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
始终 returns 为真。
显然,这不是特别实用,但它指出了可以用来比较异构序列的相关构建块。
SemantiComparison 提供了一个 SemanticComparer<T>
class 来实现 IEqualityComparer<T>
,但它只适用于相同类型的值。因此,为了使用它来比较异构序列,您需要将其中一个列表映射到另一种类型的序列中。
通常,您周围已经有了这样的地图,但如果没有,这也是构建地图的良好动力。否则,您可以使用像 AutoMapper.
这样的语义映射器例如,假设您有一个 Foo
class 这样的:
public class Foo
{
public int Number { get; set; }
public string Text { get; set; }
}
和另一个Bar
class,非常相似:
public class Bar
{
public int Number { get; set; }
public string Text { get; set; }
}
您现在可以使用地图比较 foos 和 bars,并且 SemanticComparison<Bar>
:
[Fact]
public void TestEquivalentSequences()
{
var foos = new[]
{
new Foo { Number = 42, Text = "ploeh" },
new Foo { Number = 1337, Text = "fnaah" }
};
var bars = new[]
{
new Bar { Number = 42, Text = "ploeh" },
new Bar { Number = 1337, Text = "fnaah" }
};
AutoMapper.Mapper.CreateMap<Foo, Bar>();
Assert.True(
foos.Select(AutoMapper.Mapper.Map<Bar>).SequenceEqual(
bars,
new SemanticComparer<Bar>()),
"Mapped arrays should be equivalent.");
}
不过,如果你给你的对象结构平等,它会让你的生活变得更轻松。此答案仅勾勒出可能的内容,而不是推荐的内容。