我们写了一个测试,如下所示。 此测试需要,我们已经建立的连接Equal
的-过载CodeTableItem
-class:
ICollection<CodeTableItem> expectedValutaList = new List<CodeTableItem>();
expectedValutaList.Add(new CodeTableItem("DKK", "DKK"));
expectedValutaList.Add(new CodeTableItem("EUR", "EUR"));
RepoDac target = new RepoDac();
var actual = target.GetValutaKd();
CollectionAssert.AreEqual(expectedValutaList.ToList(),actual.ToList());
测试工作正常,但不幸的依赖关系的Equality
功能全,意思是如果我延长CodeTableItem
-class多一个领域,而忘记延长Equals
功能全,单元测试仍然运行绿,虽然我们不考所有字段。 我们希望避免这种Equality
的污染(见测试具体的平等 ),已经只写了符合测试。
我们已经尝试使用OfLikeness
,并改写这样的测试:
ICollection<CodeTableItem> expectedValutaList = new List<CodeTableItem>();
expectedValutaList.Add(new CodeTableItem("DKK", "DKK"));
expectedValutaList.Add(new CodeTableItem("EUR", "EUR"));
var expectedValutaListWithLikeness =
expectedValutaList.AsSource().OfLikeness<List<CodeTableItem>>();
RepoDac target = new RepoDac();
ICollection<CodeTableItem> actual;
actual = target.GetValutaKd();
expectedValutaListWithLikeness.ShouldEqual(actual.ToList());
但由于测试失败Capacity
是不相等的。 我写了通过反射多次运行的代码,通常最终实现忽视领域的过载。 有没有办法忽略与某些字段OfLikeness
或ShouldEqual
? 还是有解决这个问题的一些其他的方式?
为什么你不想那样做
我不认为任何创造一个神似List<T>
你想要做什么就做。 据我了解,你要的内容比较两个列表。 那是不一样的比较两个列表...
考虑神似做什么:它比较属性值。 什么是属性List<T>
他们是
作为尼科斯Baxevanis在他的回答中指出,可以使用不讲究方法忽略容量属性的值,但是这意味着只有Count属性仍然存在。
换句话说,如果你这样做,这一点:
expectedValutaListWithLikeness.ShouldEqual(actual.ToList());
在功能上等价于:
Assert.AreEqual(expected.Count, actual.Count)
换句话说,名单可能有完全不同的数据,但测试仍然会通过只要每个列表具有的元素是相同的。 这可能不是你想要的...
你应该做的
您可以使用象形互相反对的每个元素进行比较。 像这样的东西应该工作:
var expectedValutaList = new List<CodeTableItem>();
expectedValutaList.Add(new CodeTableItem("DKK", "DKK"));
expectedValutaList.Add(new CodeTableItem("EUR", "EUR"));
var expectedValutaListWithLikeness = from cti in expectedValutaList
select cti
.AsSource()
.OfLikeness<CodeTableItem>();
var target = new RepoDac();
var actual = target.GetValutaKd();
Assert.IsTrue(expectedValutaListWithLikeness.Cast<object>().SequenceEqual(
actual.Cast<object>()));
您可能还可以使用CollectionAssert的说法,但它已经这么多年了,因为我最后一次使用MSTest的,我不记得方法的怪癖...
只需添加.Without(x => x.Capacity)
和相象实例将忽略Capacity
比较值时,属性。
var expectedValutaListWithLikeness =
expectedValutaList.AsSource().OfLikeness<List<CodeTableItem>>()
.Without(x => x.Capacity);
更新:
正如马克·塞曼在他的回答中指出,你可能想要的是对对方的每个元素进行比较。 这里有一个稍微不同的方式,使您可以进行非常灵活的对比。
假设RepoDac类返回是这样的:
public class RepoDac
{
public ICollection<CodeTableItem> GetValutaKd()
{
return new[]
{
new CodeTableItem("DKK", "DKK"),
new CodeTableItem("EUR", "EUR")
};
}
}
有关每个实例expectedValutaList
您可以创建一个覆盖使用神似等于动态代理:
var object1 = new CodeTableItem("DKK", "DKK1")
.AsSource().OfLikeness<CodeTableItem>()
.Without(x => x.Property2)
.CreateProxy();
var object2 = new CodeTableItem("EUR2", "EUR")
.AsSource().OfLikeness<CodeTableItem>()
.Without(x => x.Property1)
.CreateProxy();
注意object1和对象2怎么会有甚至不同的动态生成等于。 (第一忽略Property2而第二忽略Property1。)
下面通过测试:
var expected = new List<CodeTableItem>();
expected.Add(object1);
expected.Add(object2);
var target = new RepoDac();
var actual = target.GetValutaKd();
Assert.IsTrue(expected.SequenceEqual(actual));
注意:
需要将开始与expected
包含动态生成的代理(压倒一切的Equals)实例。
您可能会发现该功能的详细信息在这里 。
我想更加明确,对遇到此问题的人 - 使用鲁本的第二个代码示例,要比较这两个日历和Calendar.Holidays,而定制两者的对比:
var expectedCalendar = newCalendar.AsSource()
.OfLikeness<Calendar>()
.Without(c=>c.Id) //guid, will never be equal
.With(c=>c.Holidays).EqualsWhen((source, dest) =>
source.Holidays.SequenceLike(dest.Holidays, holiday =>
holiday.Without(h=>h.SecondsUntil) //changes every second
));
在这个例子中,你首先设置属性排除等日历对象。 然后你给一个自定义EqualsWith实施处理假期集合。 假日=>拉姆达然后允许您自定义的孩子比较,就像父母。 您可以继续筑巢,只要你喜欢很多括号。
以下的答案必须从发出我问自己这个问题的一个副本 ,见下文
你可以使用一个SequenceLike
这暗示LINQ的操作SequenceEqual
运营商。
这可以写出: -
[Theory, AutoData]
public void ShouldMap( Dto inputDto )
{
var mapped = inputDto.ToModel();
inputDto.AsSource().OfLikeness<Model>()
.Without( x => x.IgnorableProperty )
.With( x => x.Tags ).EqualsWhen( ( dto, model ) =>
model.Tags.SequenceLike( dto.Tags ) )
.ShouldEqual( mapped );
}
闪亮短实现了基于@马克西曼的回答感谢,以从@Nikos Baxevanis提示所有功能于一身的帮手: -
static class LikenessSequenceExtensions
{
public static bool SequenceLike<T, TSource>( this IEnumerable<T> that, IEnumerable<TSource> source )
{
return SequenceLike<T, TSource>( that, source, x => x );
}
public static bool SequenceLike<T, TSource>( this IEnumerable<T> that, IEnumerable<TSource> source, Func<Likeness<TSource, T>, IEquatable<T>> customizeLikeness )
{
return source.Select( x => customizeLikeness( x.AsSource().OfLikeness<T>() ) ).SequenceEqual( that.Cast<object>() );
}
}
我原来的执行:
static class LikenessSequenceExtensions0
{
public static bool SequenceLike0<T, TSource>( this T[] that, TSource[] source )
{
return source.SequenceLike0( that, likeness => likeness );
}
public static bool SequenceLike0<T, TSource>( this T[] that, TSource[] source, Func<Likeness<TSource, T>, IEquatable<T>> customizeLikeness )
{
return source.SequenceEqual( that, ( x, y ) => customizeLikeness( x.AsSource().OfLikeness<T>() ).Equals( y ) );
}
public static bool SequenceEqual<T, TSource>( this T[] that, TSource[] source, Func<T, TSource, bool> equals )
{
return that.Length == source.Length && that.Zip( source, Tuple.Create ).All( x => equals( x.Item1, x.Item2 ) );
}
}
副本原件问题
我在寻找管理干净的方式测试特定的平等的阵列/ IEnumerable<T>
/ seq<'T>
在我基础xunit.AutoFixture测试。
开箱即用(我已经失去了参考在那里我学到这一点), Ploeh.SemanticComparison
的Likeness
版本到2.12的作品只有个别项目。
什么是相同的技术应用于项目的集合(理想的开箱即用的,而是扩展方法,良好的判断套件非常开放的),以方便表达,其中包括以组合的方式嵌入对象的项目肖像的最佳方式?
这确实是一个自我的答案,所以我可以藏匿的助手,并允许地方放一个“你做这种方式以V NN”神似应该在未来提供序列的支持,但它不会是我第一次”一直在惊讶与答案的精妙之处可能从受灾爱好者
我不知道,如果这个问题仍然是相关的,但你正在寻找的是https://github.com/jmansar/SemanticComparisonExtensions
您可以使用.WithCollectionInnerLikeness()做比较,集合,它会得到你想要的到底是什么。
文章来源: Applying [AutoFixture] SemanticComparison OfLikeness to sequences / collections / arrays / IEnumerable