Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用C比较两个Json对象#_C#_Unit Testing_Json.net_Assertion_Fluent Assertions - Fatal编程技术网

C# 如何使用C比较两个Json对象#

C# 如何使用C比较两个Json对象#,c#,unit-testing,json.net,assertion,fluent-assertions,C#,Unit Testing,Json.net,Assertion,Fluent Assertions,我有两个Json对象需要比较,如下所示。我正在使用Newtonsoft库进行Json解析 string InstanceExpected = jsonExpected; string InstanceActual = jsonActual; var InstanceObjExpected = JObject.Parse(InstanceExpected); var InstanceObjActual = JObject.Parse(InstanceActual); 我用流畅的断言来比较。但问题

我有两个Json对象需要比较,如下所示。我正在使用Newtonsoft库进行Json解析

string InstanceExpected = jsonExpected;
string InstanceActual = jsonActual;
var InstanceObjExpected = JObject.Parse(InstanceExpected);
var InstanceObjActual = JObject.Parse(InstanceActual);
我用流畅的断言来比较。但问题是,只有当属性计数/名称不匹配时,Fluent断言才会失败。如果json值不同,则传递。当值不同时,我需要失败

InstanceObjActual.Should().BeEquivalentTo(InstanceObjExpected);
例如,我将实际和预期的json进行比较,如下所示。用上面的比较方法,让他们通过,这是错误的

{
  "Name": "20181004164456",
  "objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"  
}

{
  "Name": "AAAAAAAAAAAA",
  "objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"  
}

将json反序列化为C#对象后,正确的方法是在反序列化的类中实现IComparable接口并比较这两个对象

因此:

使用系统;
使用System.Collections.Generic;
类MyObj:i可比
{
公共字符串名称{get;set;}
公共字符串ObjectID{get;set;}
公共内部比较(MyObj其他)
{
if((this.Name.CompareTo(other.Name)==0)&&
(this.ObjectID.CompareTo(other.ObjectID)==0))
{
返回0;
}
返回-1;
}
}

一个选项是将json字符串反序列化为C#对象并进行比较

与使用
JToken.DeepEquals
(正如@JessedeWit所建议的那样)相比,这种方法需要更多的工作,但它的优点是,如果测试失败,可以提供更好的错误消息(参见下面的屏幕截图)

您的json字符串可以建模为以下类:

public class Entity
{
    [JsonProperty("Name")]
    public string Name { get; set; }

    [JsonProperty("objectId")]
    public string ObjectId { get; set; }
}
在测试中,将json字符串反序列化为对象并进行比较:

[TestFixture]
public class JsonTests
{
    [Test]
    public void JsonString_ShouldBeEqualAsExpected()
    {
        string jsonExpected = @"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
        string jsonActual = @"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";

        Entity expectedObject = JsonConvert.DeserializeObject<Entity>(jsonExpected);
        Entity actualObject = JsonConvert.DeserializeObject<Entity>(jsonActual);

        actualObject.Should().BeEquivalentTo(expectedObject);
    }
}
[TestFixture]
公共类JsonTests
{
[测试]
public void JsonString_应为QUALASExpected()
{
字符串jsonExpected=@“{”名称“:”20181004164456“,”对象ID“:”4ea9b00b-d601-44af-a990-3034af18fdb1%>”;
字符串jsonActual=@“{”“名称”“:”“AAAAAAAAAAAA”“objectId”“:”“4ea9b00b-d601-44af-a990-3034af18fdb1%>”“}”;
实体expectedObject=JsonConvert.DeserializeObject(jsonExpected);
实体actualObject=JsonConvert.DeserializeObject(jsonActual);
actualObject.Should().BeEquivalentTo(expectedObject);
}
}
PS:我在测试方法中使用了NUnit和FluentAssertions。运行测试:


考虑使用Newtonsoft提供的
JToken.DeepEquals()
方法。无论您使用的是哪种测试框架,它看起来都有点像这样:

Console.WriteLine(JToken.DeepEquals(InstanceObjActual, InstanceObjExpected));
// false

我做了更多的挖掘,并且能够找出OP的测试代码没有按预期运行的原因。我可以通过安装和使用nuget软件包来修复它

有一点很重要:

确保使用FluentAssertions.Json包含
,否则为false
可能会出现积极的情况

测试代码如下所示:

using FluentAssertions;
using FluentAssertions.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;

[TestFixture]
public class JsonTests
{
    [Test]
    public void JsonObject_ShouldBeEqualAsExpected()
    {
        JToken expected = JToken.Parse(@"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
        JToken actual = JToken.Parse(@"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");

        actual.Should().BeEquivalentTo(expected);
    }
}
运行测试:


提出了一种非递归的方法,可以移除双胞胎——其思想是从非常相似的JSON中移除相同的元素,以便每个对象中只保留不同的节点:

public void RemoveTwins(ref BreadthFirst bf1, ref BreadthFirst bf2) {
    JsonNode traversal = bf1.Next();
    Boolean removed = false;
    do {
        if (!removed) {
            if (bf2.Current != null) while (bf1.Level == bf2.Level && bf2.Next() != null) ;
            if (bf2.Current != null) while (bf1.Level != bf2.Level && bf2.Next() != null) ;
            else bf2.Current = bf2.root;
        }
        else traversal = bf1.Next();
        if (bf2.Level < 0) bf2.Current = bf2.Root;
        do {
            removed = bf1.NextAs(bf1.src, bf2, bf2.src);
            if (removed && bf1.Orphan && bf2.Orphan) {
                JsonNode same = bf1.Current.Parent;
                traversal = bf1.RemoveCurrent();
                same = bf2.Current.Parent;
                bf2.RemoveCurrent();
                bf1.UpdateLevel();
                bf2.UpdateLevel();
                if (traversal == null
                || bf1.Root == null || bf2.Root == null
                || (bf1.Level == 0 && bf1.Current.NodeBelow == null)) {
                    traversal = null;
                    break;
                }
            } else
            if (!removed) {
                break; 
            } else removed = false;
        } while (removed);
        if (!removed) traversal = bf1.Next();
    } while (traversal != null);
}
public void RemoveTwins(ref-BreadthFirst bf1,ref-BreadthFirst bf2){
JsonNode遍历=bf1.Next();
布尔值=假;
做{
如果(!已删除){
if(bf2.Current!=null)而(bf1.Level==bf2.Level&&bf2.Next()!=null);
if(bf2.Current!=null)而(bf1.Level!=bf2.Level&&bf2.Next()!=null);
否则bf2.Current=bf2.root;
}
else遍历=bf1.Next();
如果(bf2.Level<0)bf2.Current=bf2.Root;
做{
移除=bf1.NextAs(bf1.src、bf2、bf2.src);
如果(已删除(&bf1.Orphan&&bf2.Orphan){
JsonNode same=bf1.Current.Parent;
traversal=bf1.RemoveCurrent();
相同=bf2.Current.Parent;
bf2.RemoveCurrent();
bf1.UpdateLevel();
bf2.UpdateLevel();
if(遍历==null
||bf1.Root==null | | bf2.Root==null
||(bf1.Level==0&&bf1.Current.NodeBelow==null)){
遍历=空;
打破
}
}否则
如果(!已删除){
打破
}else=false;
}同时(移除);
如果(!removed)遍历=bf1.Next();
}while(遍历!=null);
}
在我的GitHub上完成代码+解析器(配置文件或以下)。

旧的CSV版本也对我在这里的问题中提到的输入进行排序(新的版本没有,因此当一个对象的顺序颠倒时,它可能会非常慢-在解析过程中排序会更容易,或者至少在第一个搜索步骤中比较双胞胎的两个邻居)

为什么不比较字符串,而不是比较json对象?简单的字符串比较不管用吗
jsonExpected==jsonActual
。JSON实际上不是字符串,所以上面的注释是不相关的<代码>{id:“5”}
应与
{id:“5”}
相同。因此,您不能使用字符串比较器来比较JSON。。。。除非JSON总是由相同的过程创建,并且项目是有序的。@JessedeWit…我不提倡字符串比较,因为它很讨厌,但是,如果通过一个序列化程序进行往返,从而保证属性的顺序,它可能会起作用。实现
IEquatable
并覆盖
Equals
GetHashCode
会更有意义,因为只有当它们相等或不相等时,才没有好的方法来说明哪一个更大。你是对的。忘了有足够的出口。me==太老了。比我快10秒:)这是正确的答案。好东西,这是比我更简单更干净的解决方案。我在单元测试中使用
JToken.DeepEquals
发现的唯一问题是无法找到json字符串中的差异。将json反序列化为C#对象并对其进行比较会给出更好的错误消息(参见我的答案附带的屏幕截图)
public void RemoveTwins(ref BreadthFirst bf1, ref BreadthFirst bf2) {
    JsonNode traversal = bf1.Next();
    Boolean removed = false;
    do {
        if (!removed) {
            if (bf2.Current != null) while (bf1.Level == bf2.Level && bf2.Next() != null) ;
            if (bf2.Current != null) while (bf1.Level != bf2.Level && bf2.Next() != null) ;
            else bf2.Current = bf2.root;
        }
        else traversal = bf1.Next();
        if (bf2.Level < 0) bf2.Current = bf2.Root;
        do {
            removed = bf1.NextAs(bf1.src, bf2, bf2.src);
            if (removed && bf1.Orphan && bf2.Orphan) {
                JsonNode same = bf1.Current.Parent;
                traversal = bf1.RemoveCurrent();
                same = bf2.Current.Parent;
                bf2.RemoveCurrent();
                bf1.UpdateLevel();
                bf2.UpdateLevel();
                if (traversal == null
                || bf1.Root == null || bf2.Root == null
                || (bf1.Level == 0 && bf1.Current.NodeBelow == null)) {
                    traversal = null;
                    break;
                }
            } else
            if (!removed) {
                break; 
            } else removed = false;
        } while (removed);
        if (!removed) traversal = bf1.Next();
    } while (traversal != null);
}