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

JUnit 4.12本地Eclipse运行出ComparisonFailure但远程执行正常求助

解决JUnit本地JSON对比时的org.junit.ComparisonFailure隐形格式问题

这种情况我之前排查过好几次,明明肉眼看预期和实际的JSON内容完全一致,但JUnit就是报对比失败,还高亮空格位置——核心原因通常是隐形的格式差异:比如换行符、缩进方式、或者JSON序列化的细微配置不同,远程环境和本地Eclipse的环境差异放大了这个问题。下面给你几个实用的排查和解决思路:

1. 检查JSON文件的换行符类型

远程服务器一般用LF(\n)作为换行符,而Windows本地的Eclipse默认可能会把文件保存为CRLF(\r\n)。当你读取expected的JSON文件时带了\r\n,但actual是ObjectMapper生成的默认用LF,就会导致每一行结尾的字符不一样,肉眼看不到但JUnit能检测到。

  • 用Notepad++打开你的signedCasesReportView01.json,查看右下角的换行符标识(比如显示CRLF或LF)。
  • 如果和本地序列化的换行符不一致,直接改成一致的(比如改成LF,或者让ObjectMapper生成CRLF)。

2. 统一ObjectMapper的序列化配置

不同环境下ObjectMapper的默认配置可能有差异,比如缩进空格数、是否自动排序键、换行符类型等。你可以显式配置ObjectMapper,让生成的JSON格式完全固定:

ObjectMapper objectMapper = new ObjectMapper();
// 强制统一换行符为LF(和远程一致)
objectMapper.configure(JsonGenerator.Feature.WRITE_EOL_AS_LF, true);
// 如果需要固定缩进格式(和JSON文件保持一致)
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
// 确保键的顺序和JSON文件一致(避免序列化时自动排序)
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, false);

这样生成的actual格式就和expected文件完全对齐了,不会出现隐形差异。

3. 用JSON断言库忽略格式差异

如果你的测试只关心JSON的内容和结构,不要求格式完全一致,可以用JSONAssert库来代替JUnit原生的assertEquals,它能自动忽略空格、换行、键顺序这些格式差异:

首先添加Maven依赖:

<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>jsonassert</artifactId>
    <version>1.5.1</version>
    <scope>test</scope>
</dependency>

然后修改测试代码:

import org.skyscreamer.jsonassert.JSONAssert;

@Test 
public void calculateSignedCasesView() throws JsonProcessingException { 
    Case case1 = prepareCase(); 
    getEm().persist(case1); 
    SignedCasesViewFilter filter = new SignedCasesViewFilter(
        new LinkedHashSet<>(Arrays.asList("testCode")), 
        new Date(0), 
        new Date(0)
    ); 
    SignedCasesView view = reportService.calculateSignedCasesView(filter); 
    String actual = getObjectMapper().writeValueAsString(view); 
    String expected = readToString("signedCasesReportView01.json"); 
    // 第三个参数设为false,忽略格式差异只对比内容
    JSONAssert.assertEquals(expected, actual, false); 
}

4. 排查隐形字符差异

如果上面的方法都没用,可以把expected和actual的每个字符打印出来,查看ASCII码,找出肉眼看不到的差异:

// 辅助方法:打印字符串每个字符的ASCII码
private void printCharDetails(String str, String label) {
    System.out.println("=== " + label + " 字符详情 ===");
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        System.out.printf("第%d位: '%c' (ASCII: %d, 十六进制: 0x%04X)%n", 
            i+1, c, (int)c, (int)c);
    }
}

// 在测试中调用
printCharDetails(expected, "expected");
printCharDetails(actual, "actual");

运行后对比输出,就能看到是不是有非打印字符(比如\r、全角空格、零宽空格等)在搞鬼。

内容的提问来源于stack exchange,提问作者Pivoman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:58:27