Go测试中如何处理XML反序列化后的空白字符?
XML反序列化测试中chardata字段空白字符的处理方案
问题场景
测试parseFruitXML函数时,结构体Fruits的Cherries字段带有,chardata标签,反序列化XML时会积累文档中的换行、缩进等空白字符,导致reflect.DeepEqual对比got和预定义的want结构体时失败,需要选择合适方式处理这些空白。
方案1:在want中匹配原始空白字符
直接在want的Cherries字段中写入XML实际存在的空白内容,比如:
want := Fruits{ XMLName: xml.Name{ Local: "fruit", }, Cherries: "\n ", // 对应fruit根节点下的换行与缩进 Apples: 10, Oranges: 20, }
- 优势:完全贴合XML原始内容,无需修改反序列化结果
- 劣势:对XML格式变化极度敏感,缩进、换行调整后必须同步更新
want,维护成本高
方案2:清理got字段的空白后再对比
在执行reflect.DeepEqual前,用strings.TrimSpace()清理got.Cherries的首尾空白:
got, err := parseFruitXML(b) if err != nil { t.Fatal(err) } // 清理Cherries字段的首尾空白 got.Cherries = strings.TrimSpace(got.Cherries) if !reflect.DeepEqual(got, want) { t.Errorf("got %+v\n, want %+v", got, want) }
- 优势:测试逻辑更健壮,不受XML格式(缩进、换行)变化影响
- 劣势:如果业务需要保留
Cherries字段的合法首尾空白,该方式会破坏原始数据
方案3:自定义字段比较逻辑
如果Cherries的空白不影响业务逻辑,编写自定义比较函数,忽略该字段的空白差异:
func equalFruits(a, b Fruits) bool { if a.XMLName != b.XMLName { return false } if a.Apples != b.Apples { return false } if a.Oranges != b.Oranges { return false } // 忽略Cherries字段的空白差异,仅对比有效内容 return strings.TrimSpace(a.Cherries) == strings.TrimSpace(b.Cherries) }
测试中替换reflect.DeepEqual使用该函数:
if !equalFruits(got, want) { t.Errorf("got %+v\n, want %+v", got, want) }
- 优势:灵活性最高,可针对不同字段制定比较规则,既不破坏原始数据,也适配XML格式变化
- 劣势:需要额外编写比较代码,结构体字段较多时会增加代码量
方案4:移除不必要的chardata标签
如果业务上不需要捕获XML中的字符数据,直接移除Cherries字段的,chardata标签:
type Fruits struct { XMLName xml.Name `xml:"fruit"` Cherries string // 移除,chardata标签 Apples int `xml:"apples"` Oranges int `xml:"oranges"` }
- 优势:从根源解决问题,无需修改测试代码
- 劣势:仅适用于业务不需要chardata的场景,若需捕获合法字符数据则不可用
内容的提问来源于stack exchange,提问作者hitzoglin
相关产品推荐
相关产品推荐

