为何使用Assert.Equal比较不同JObject会通过?
问题解析与解决方案
核心原因
你遇到的结果不一致问题,本质是两种相等比较逻辑的差异:
JObject.Equals():继承自JToken的默认实现,是引用相等比较——只有当两个变量指向同一个JObject实例时才返回true,所以jobj1.Equals(jobj2)失败是正常的(它们是不同实例)。- xUnit的
Assert.Equal():默认使用EqualityComparer<T>.Default做相等判断。对于JObject这类实现了集合接口的类型,xUnit会尝试遍历键值对做结构比较,但它并没有适配Newtonsoft.Json的JSON内容比较逻辑,导致出现不符合预期的结果(比如错误认为不同类型的JSON值相等)。
该研究哪个?
核心问题在Newtonsoft.Json的相等比较设计:官方专门提供了JToken.DeepEquals()方法来实现JSON对象的深度内容比较,这才是正确判断两个JObject内容是否一致的标准方式。xUnit的默认比较器只是没有针对性适配JSON对象,不需要深入研究xUnit,重点看Newtonsoft.Json的文档即可。
正确的单元测试写法
放弃依赖xUnit的Assert.Equal()比较JObject,改用官方推荐的JToken.DeepEquals():
using Newtonsoft.Json.Linq; namespace TestProject1 { public class UnitTest1 { [Fact] public void Test1() { JObject jobj1 = JObject.FromObject(new { foo = "bar" }); JObject jobj2 = JObject.FromObject(new { foo = 1 }); JObject jobj3 = JObject.FromObject(new { foo = "b" }); // 内容不同,断言失败(符合预期) Assert.True(JToken.DeepEquals(jobj1, jobj2)); // 内容不同,断言失败(符合预期) Assert.True(JToken.DeepEquals(jobj1, jobj3)); } } }
补充说明
你看到的奇怪结果(Assert.Equal(jobj1, jobj2)通过)大概率是版本兼容性问题,旧版xUnit或Newtonsoft.Json的默认比较器对JValue的类型判断存在疏漏。但无论版本如何,JToken.DeepEquals()都是最可靠的JSON内容比较方式,能准确判断两个JSON对象的键、值类型、值内容是否完全一致。
内容的提问来源于stack exchange,提问作者zhangr4
相关产品推荐
相关产品推荐

