You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:27:06