IntelliJ运行Spock测试比对大字符串时挂起如何解决
Spock大体积XML字符串比对导致IntelliJ测试运行器挂起的解决方案
- 关闭测试失败自动预览差异功能
打开IntelliJ设置路径:File | Settings | Build, Execution, Deployment | Build Tools | JUnit,取消勾选Open diff viewer when tests fail选项,也可以在对应测试的运行配置的「Modify options」中单独关闭该配置。该功能默认会在测试失败时提前拉取全部预期、实际字符串做diff渲染,十万级字符的diff计算会直接卡住UI线程,关闭后仅在你主动点击查看差异时才会触发计算,不会提前挂起运行器。 - 改用XML结构化比对替代原始字符串比对
不要直接比对全量XML字符串,先将字符串解析为DOM对象,使用XMLUnit这类结构化比对工具做校验,不仅能规避超长输出问题,还能自动过滤缩进、换行、注释这类不影响业务逻辑的差异,测试稳定性更高,示例代码如下:
结构化比对仅会输出存在差异的节点信息,不会全量打印十多万字符的完整内容,自然不会触发运行器卡顿。import org.xmlunit.builder.DiffBuilder def "xml 业务逻辑比对测试"() { given: def expectedXml = "你的预期XML字符串" def actualXml = "接口/逻辑返回的实际XML字符串" when: def diff = DiffBuilder.compare(expectedXml) .withTest(actualXml) .ignoreWhitespace() .ignoreComments() .build() then: !diff.hasDifferences() } - 自定义断言逻辑,截断超长输出
在断言中自定义错误输出规则,比对失败时仅打印差异位置附近的片段,把完整的XML内容写入本地临时文件,避免全量内容输出到测试结果面板,示例代码如下:then: if (expectedXml != actualXml) { // 计算首个差异的字符位置 int diffPos = 0 int maxLen = Math.min(expectedXml.length(), actualXml.length()) while (diffPos < maxLen && expectedXml.charAt(diffPos) == actualXml.charAt(diffPos)) { diffPos++ } // 全量差异写入本地文件,不输出到控制台 File diffLog = new File("build/test-xml-diff-${System.currentTimeMillis()}.log") diffLog.text = "=== EXPECTED ===\n${expectedXml}\n\n=== ACTUAL ===\n${actualXml}" // 仅输出差异附近的2000字符 int snippetStart = Math.max(0, diffPos - 1000) int expectedSnippetEnd = Math.min(expectedXml.length(), diffPos + 1000) int actualSnippetEnd = Math.min(actualXml.length(), diffPos + 1000) throw new AssertionError("XML比对失败,差异位置:第${diffPos}字符,完整差异已写入${diffLog.absolutePath}\n" + "差异片段预览:\n预期:${expectedXml.substring(snippetStart, expectedSnippetEnd)}\n" + "实际:${actualXml.substring(snippetStart, actualSnippetEnd)}") } - 调大测试运行器的输出缓冲区上限
在测试运行配置的「VM options」中添加参数-Didea.test.cyclic.buffer.size=4194304,将默认1M的测试输出缓冲区调整为4M,避免超长输出触发缓冲区溢出导致的UI线程阻塞。
内容的提问来源于stack exchange,提问作者spartanhooah
相关产品推荐
相关产品推荐

