JUnit测试Apache Camel路由:Drone构建中assertEquals断言失败
这种情况十有八九是换行符差异导致的——本地开发环境(大概率是Windows)使用CRLF(\r\n)作为换行符,而Drone CI的运行环境一般是Linux,仅使用LF(\n)换行。虽然日志打印出来的内容看起来完全一致,但实际字符串的字节结构存在差异,这就导致断言在CI环境中莫名失败。
问题分析
你定义的EXPECTED_RESULT用的是\n作为换行符,但本地路由处理生成的消息体可能自动带上了Windows风格的\r(比如读取本地文件、部分组件默认使用系统换行符)。在本地控制台打印时,\r\n会被自动解析为换行,看起来和\n没区别;但字符串直接比较时,\r的存在会让两个字符串判定为不相等——而CI环境中生成的消息体可能是纯LF格式,和你的预期字符串格式不匹配,最终导致断言失败。
解决方法
你可以通过以下几种方式统一处理换行符,消除环境差异:
1. 统一替换换行符后再比较
直接将实际结果和预期结果中的所有换行符转换为统一格式(比如LF),再进行断言:
@Test public void testFileCreation() throws Exception{ // ... 其他测试代码 List<Exchange> exchanges = resultEndpoint.getExchanges(); String actual = exchanges.get(0).getIn().getBody().toString() // 替换所有CRLF或LF为统一的LF .replaceAll("\\r\\n?", "\n"); Assert.assertEquals(EXPECTED_RESULT, actual); }
2. 使用工具类标准化文本格式
如果你的消息体是纯文本,可以用Apache Commons Lang的StringUtils.normalizeSpace方法,它会将所有换行、回车、制表符等特殊空白字符转换为单个空格,同时去掉首尾空白——适合只关心文本内容、不纠结换行格式的场景:
// 需要先引入commons-lang3依赖 import org.apache.commons.lang3.StringUtils; @Test public void testFileCreation() throws Exception{ // ... 其他测试代码 List<Exchange> exchanges = resultEndpoint.getExchanges(); String actual = StringUtils.normalizeSpace(exchanges.get(0).getIn().getBody().toString()); String expected = StringUtils.normalizeSpace(EXPECTED_RESULT); Assert.assertEquals(expected, actual); }
3. 在Camel路由中强制指定换行符
从根源解决问题,确保路由生成的消息体始终使用统一的换行符(比如LF)。比如在处理消息体的节点显式替换换行符:
from("...") .setBody(body().replaceAll("\\r\\n?", "\n")) .to("mock:result");
验证方法
如果还不确定是不是换行符的问题,可以在断言前打印字符串的字节数组,直观看到差异:
import java.util.Arrays; // ... 测试代码中 String actualStr = exchanges.get(0).getIn().getBody().toString(); String expectedStr = EXPECTED_RESULT; System.out.println("Actual bytes: " + Arrays.toString(actualStr.getBytes())); System.out.println("Expected bytes: " + Arrays.toString(expectedStr.getBytes()));
比如Windows下的\r\n对应的字节是[13, 10],而Linux的\n是[10],通过字节数组就能一眼看出差异所在。
内容的提问来源于stack exchange,提问作者Jaswanth Bellam

