问题描述
我想结合流利断言的集合断言和属性断言,例如断言两个的IEnumerable
的使用属性由属性(可能是嵌套)比较(即结构性平等,函数式语言的说法)两两相等。
具体的例子:
VAR DIC =新词典< INT,串>( ){{1,喜},{2,再见}};
VAR实际= dic.ToSelectListItems(0).OrderBy(SI => si.Text);
VAR预期=新的List< SelectListItem>(){
新SelectListItem(){选择=假,文本=再见,值=2},
新SelectListItem(){选择=假,文本=喜,值=1}
};
下面我写了一个扩展方法 ToSelectListItems
的转换一个词典
到的IEnumerable
的 SelectListItem
S(从ASP.NET MVC)。我想断言,实际
和有望
是结构平等,并指出引用类型 SelectListItem
不覆盖等于
和因此默认使用引用相等。
更新
目前使用下面的手卷解决方案,仍然希望更好的东西内置到FluentAssertions:
公共静态无效ShouldBeStructurallyEqualTo< T,U>(这个IEnumerable的< T>实际,IEnumerable的< U>预期){
actual.Should()HaveCount (expected.Count());
actual.Zip(预期).ForEach(对= GT; pair.Item1.ShouldHave()AllProperties()IncludingNestedObjects()EqualTo(pair.Item2)。);
}
(注:邮编
这里是使用 Tuple.Create
作为默认的投影)
的IEnumerable
延伸b 更新2
下面是两个很小的例子:
公共类FooBar的{
公共字符串美孚{搞定;组; }
公众诠释吧{搞定;组; }
}
公共类识别TestClass {
[测试]
公共无效MinimalExample(){
名单,LT; FooBar的> enumerable1 =新的List<&FooBar的GT;(){新FooBar的(){美孚=X,酒吧= 1},新的FooBar的(){美孚=Y,酒吧= 2}};
名单,LT; FooBar的> enumerable2 =新的List<&FooBar的GT;(){新FooBar的(){美孚=X,酒吧= 1},新的FooBar的(){美孚=Y,酒吧= 2}}; 。
enumerable1.ShouldHave()SharedProperties()IncludingNestedObjects()EqualTo(enumerable2);
//测试TestClass.MinimalExample'失败:System.Reflection.TargetParameterCountException:参数数量不匹配。
//在System.Reflection.RuntimeMethodInfo.Invoke(obj对象,的BindingFlags invokeAttr,粘结剂粘合,对象[]参数,CultureInfo的文化,布尔skipVisibilityChecks)在System.Reflection.RuntimeMethodInfo.Invoke
//( obj对象,的BindingFlags invokeAttr,粘合剂粘合,在System.Reflection.RuntimePropertyInfo.GetValue(obj对象,的BindingFlags invokeAttr,宾德Binder对象[]参数,CultureInfo的文化)
//,对象[]索引,CultureInfo的文化)
//在System.Reflection.RuntimePropertyInfo.GetValue(obj对象,对象[]指数)
//在FluentAssertions.Assertions.PropertyEqualityValidator.AssertSelectedPropertiesAreEqual(对象主体,客体预期)
//在FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker跟踪器,串parentPropertyName)
//在FluentAssertions.Assertions.PropertyEqualityValidator.Validate()
//在FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(对象otherObject, reason字符串,对象[] reasonArgs)
//在FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(对象otherObject)
// MiscAssertions.cs(32,0):在TestClass.MinimalExample()
}
[测试]
公共无效MinimalExample2(){
IEnumerable的<&FooBar的GT; enumerable1 =(新的List< FooBar的>(){新FooBar的(){美孚=X,酒吧= 1},新的FooBar的(){美孚=Y,酒吧= 2}})演员LT; FooBar的>( );
FooBar的[] enumerable2 =新[] {新FooBar的(){美孚=X,酒吧= 1},新的FooBar的(){美孚=Y,酒吧= 2}}; 。
enumerable1.ShouldHave()SharedProperties()IncludingNestedObjects()EqualTo(enumerable2);
//测试TestClass.MinimalExample2'失败信息:System.InvalidOperationException:请指定某些属性在比较中包括。
//在FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker跟踪器,串parentPropertyName)
//在FluentAssertions.Assertions.PropertyEqualityValidator.Validate()
//在FluentAssertions.Assertions.PropertyAssertions` 1.EqualTo(对象otherObject,字符串原因,对象[] reasonArgs)在FluentAssertions.Assertions.PropertyAssertions`1.EqualTo
//(对象otherObject)
// MiscAssertions.cs(52.0):在TestClass.MinimalExample2()
}
}
我在流利的断言加入到主分支为您的方案的支持。这将是下一版本的一部分,但它可能会带我们一两个月来accumalate足够的变化,以保证另一个版本。如果你愿意,你可以抓住源构建和运行release.bat建立一个中间版本。
I would like to "combine" Fluent Assertion's collection assertions and property assertions, e.g. assert that two IEnumerable
's are pairwise-equal using property-by-property (possibly "nested") comparison (i.e. structural equality, in functional language parlance).
Concrete example:
var dic = new Dictionary<int, string>() { {1, "hi"}, {2, "bye" } };
var actual = dic.ToSelectListItems(0).OrderBy(si => si.Text);
var expected = new List<SelectListItem>() {
new SelectListItem() {Selected = false, Text="bye", Value="2"},
new SelectListItem() {Selected = false, Text="hi", Value="1"}
};
Here I wrote an extension method ToSelectListItems
that converts a Dictionary
to an IEnumerable
of SelectListItem
s (from ASP.NET MVC). I want to assert that actual
and expected
are "structurally" equal, noting that the reference type SelectListItem
does not override Equal
s and thus uses reference equality by default.
Update
Currently using the following hand-rolled solution, still hoping for something better built into FluentAssertions:
public static void ShouldBeStructurallyEqualTo<T, U>(this IEnumerable<T> actual, IEnumerable<U> expected) {
actual.Should().HaveCount(expected.Count());
actual.Zip(expected).ForEach(pair => pair.Item1.ShouldHave().AllProperties().IncludingNestedObjects().EqualTo(pair.Item2));
}
(note: Zip
here is my own IEnumerable
extention which uses Tuple.Create
as the default projection)
Update 2
Here are two minimal examples:
public class FooBar {
public string Foo { get; set; }
public int Bar { get; set; }
}
public class TestClass {
[Test]
public void MinimalExample() {
List<FooBar> enumerable1 = new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } };
List<FooBar> enumerable2 = new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } };
enumerable1.ShouldHave().SharedProperties().IncludingNestedObjects().EqualTo(enumerable2);
//Test 'TestClass.MinimalExample' failed: System.Reflection.TargetParameterCountException : Parameter count mismatch.
// at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
// at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
// at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
// at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
// at FluentAssertions.Assertions.PropertyEqualityValidator.AssertSelectedPropertiesAreEqual(Object subject, Object expected)
// at FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker tracker, String parentPropertyName)
// at FluentAssertions.Assertions.PropertyEqualityValidator.Validate()
// at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject, String reason, Object[] reasonArgs)
// at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject)
// MiscAssertions.cs(32,0): at TestClass.MinimalExample()
}
[Test]
public void MinimalExample2() {
IEnumerable<FooBar> enumerable1 = (new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } }).Cast<FooBar>();
FooBar[] enumerable2 = new [] { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } };
enumerable1.ShouldHave().SharedProperties().IncludingNestedObjects().EqualTo(enumerable2);
//Test 'TestClass.MinimalExample2' failed: System.InvalidOperationException : Please specify some properties to include in the comparison.
// at FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker tracker, String parentPropertyName)
// at FluentAssertions.Assertions.PropertyEqualityValidator.Validate()
// at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject, String reason, Object[] reasonArgs)
// at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject)
// MiscAssertions.cs(52,0): at TestClass.MinimalExample2()
}
}
I have added support for your scenario in the main branch of Fluent Assertions. It will be part of the next version, but it might take us a month or two to accumalate enough changes to warrant another release. If you want, you can grab the source build and run the release.bat to build an intermediate version.
这篇关于如何用流利的-断言结合收集和财产的断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!