XUnit+Shouldly单元测试ShouldContainKeyAndValue校验字典值一致仍失败问题
问题根因
Shouldly的ShouldContainKeyAndValue方法对引用类型默认使用引用相等性做比对:你在校验时传入的new []{ "'Id' must be equal to '0'." }是新创建的数组实例,而业务逻辑返回的字典里存储的是另一个数组实例,哪怕两个数组的元素完全一致,只要引用地址不同,就会判定为值不相等。你单独校验键Id可以通过,是因为字符串是不可变类型,相等判断默认走值比对,没有引用问题。
解决方案
方案1:拆分校验(最常用,可读性最高)
先校验键存在,再单独对值做数组内容比对,Shouldly的ShouldBe对集合类型默认按元素内容比对:
// Assert result.IsSuccess.ShouldBeFalse(); result.ResultType.ShouldBe(ResultType.Invalid); var errorDict = (Dictionary<string, string[]>)result.Data; // 先校验键存在 errorDict.ShouldContainKey("Id"); // 再校验数组内容一致 errorDict["Id"].ShouldBe(new []{ "'Id' must be equal to '0'." });
方案2:链式校验
直接对取出的键值做内容断言:
((Dictionary<string, string[]>)result.Data) .ShouldContainKey("Id") .ShouldSatisfy(errors => errors.SequenceEqual(new []{ "'Id' must be equal to '0'." }));
方案3:传入自定义比较器(适合批量校验场景)
如果需要多处校验字典的数组值,可以自定义IEqualityComparer<string[]>传入ShouldContainKeyAndValue,让方法按内容比对数组:
public class StringArrayComparer : IEqualityComparer<string[]> { public bool Equals(string[] x, string[] y) { return x.SequenceEqual(y); } public int GetHashCode(string[] obj) { return obj.Aggregate(0, (hash, s) => hash ^ s.GetHashCode()); } } // 校验时使用 ((Dictionary<string, string[]>)result.Data) .ShouldContainKeyAndValue("Id", new []{ "'Id' must be equal to '0'." }, new StringArrayComparer());
内容的提问来源于stack exchange,提问作者RonRonDK
相关产品推荐
相关产品推荐

