【问题标题】:Compare 2 Json strings using Junit5 and Mockito使用 Junit5 和 Mockito 比较 2 个 Json 字符串
【发布时间】:2021-03-10 20:35:37
【问题描述】:

我有下面的 Junit。我正在尝试比较两个 Json 字符串是否具有相同的字段(顺序和值不重要)。我的测试不断失败,出现以下错误

org.opentest4j.AssertionFailedError:预期: 但是是:

@Test 
  void inputpojo_test() throws Exception {
  
  String path = "src/test/data/json_file.txt";
  String jsonString = new String(Files.readAllBytes(Paths.get(path)));
  
   Input i = new Input();
  
  ObjectMapper objectMapper = new ObjectMapper(); 
  String bean =objectMapper.writeValueAsString(i);
  
  assertEquals(bean,jsonString); 
 }

json_file.txt 是{"person_id":0,"person_name":null},输入类是

@JsonProperty("person_id") //getters and setter ommited for brevity
     int id;
    
    @JsonProperty("person_name")
     String name ;
    
    @JsonIgnore
    String value ;

【问题讨论】:

  • 无法保证键值会以相同的顺序写入,因此比较 json 字符串是没有意义的。比较节点,使用valueToTreereadTree

标签: java junit jackson mockito junit5


【解决方案1】:

我建议完全不要使用原始字符串比较 (因为它是在 JUnit 的 assertEquals 中完成的)。

相反,您应该使用一个库来比较 逻辑级别的预期和实际 JSON (即忽略空白和属性序列)。 有关详细信息,请参阅 jsonassert.skyscreamer.orgBaeldung - Introduction to JSONassert

使用这个库,您可以比较两个 JSON 字符串,而不是通过

assertEquals(bean, jsonString, true);

而是由

JSONAssert.assertEquals(bean, jsonString, true);

那么只有在“真实”差异的情况下才会出现断言错误。

【讨论】:

    【解决方案2】:

    在比较之前尝试使用trim()

    assertEquals(bean.trim(),jsonString.trim()); 
    

    这里还有一些危险的陷阱,如 cmets 中的 njzk2 所述。它适用于 trim(),因为 Jackson 按照您在 bean 中声明的顺序使用 JsonProperties,并且其中一个或两个字符串中存在一些空格。

    但是,这对于未来的版本并不安全。尝试比较实际的对象而不是字符串

    String path = "src/test/data/json_file.txt";
    String jsonString = new String(Files.readAllBytes(Paths.get(path)));
    
    ObjectMapper objectMapper = new ObjectMapper(); 
    Person bean1 =objectMapper.readValue(jsonString, Person.class);
    
    Input i = new Input();
    Person bean2 =objectMapper.readValue(i, Person.class);
      
    assertEquals(bean1, bean2); 
     }
    

    在 YourClass 中,不要忘记覆盖 .equals().hashcode() 方法,以便基于类字段进行比较。

    【讨论】:

    • 是的,可能没有在消息中打印的空格,因为它已经在输出中修剪了
    • json 标准没有指定键顺序,或者标记之间的空格,所以 2 个字符串可以表示同一个对象但不相等
    【解决方案3】:

    比较json时,最好使用语义比较,而不是字符串比较。这可以让您处理较小的格式问题,甚至是不同顺序的事情。

    您可以使用 ModelAssert - https://github.com/webcompere/model-assert

    例子

    assertJson(bean).isEqualTo(jsonString);
    

    JSONAssert 等其他库也存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 2015-06-14
      • 2012-08-16
      相关资源
      最近更新 更多