【问题标题】:XMLSerializer producing different results on TeamCityXMLSerializer 在 TeamCity 上产生不同的结果
【发布时间】:2020-04-25 04:10:00
【问题描述】:

我们为 TeamCity 添加了旧版解决方案。尽管它在本地通过,但其中一个单元测试现在失败了。

单元测试检查来自 XmlSerializer 的实际输出字符串是否符合预期。

string expectedXmlText = File.ReadAllText("TestFile.xml");
objectToSerialize = ...;

string actual = UtilsClass.SerializeObject(objectToSerialize);

Assert.That(xmlText, Is.EqualTo(expectedXmlText));

在 TeamCity 中失败并显示以下消息:

Test(s) failed.   String lengths are both 476. Strings differ at index 59.
  Expected: "..."utf-16"?>\r\n<Envelope xmlns:xsi="http://www.w3.org/2001/XM..."
  But was:  "..."utf-16"?>\r\n<Envelope xmlns:xsd="http://www.w3.org/2001/XM..."

注意命名空间不同,一个以 xsi 开头,一个以 xsd 开头。

现在我意识到 XML 在这两种情况下都是有效的,并且代表相同的东西。我也意识到你不应该编写依赖于 XML 中命名空间顺序的代码。

问题

  1. 测试 XMLSerializer 输出的正确方法是 检查输出文本有错吗?
  2. 为什么 XMLSerializer 会以不同的顺序返回命名空间?

【问题讨论】:

    标签: c# unit-testing teamcity xml-namespaces xmlserializer


    【解决方案1】:

    2.

    来自Inconsistent Namespace Order using XmlSerializer on x86/x64

    命名空间集合在内部只是一个字典。它返回值的顺序是未定义的,理论上可以在每次调用时更改。字典排序没有押韵或理由。如果您需要一致的排序,那么您必须切换到 SortedDictionary 和朋友。

    更具体地说,XmlSerializerNamespaces 在内部使用一个 Hashtable,它根据字典中已有的内容和哈希码计算项目的放置位置。 Hashtable 实际上会根据插入时发生的冲突次数定期重建字典。这记录在该类型的 MSDN 信息中。

    要点是,即使对于同一个实例,也不能保证字典的排序,因为字典(或本例中的哈希表)可以重新排序项目以提高性能。通常,我们希望看到单个实例甚至跨机器的一致行为,但不能保证。

    【讨论】:

      【解决方案2】:

      实际上有些人建议避免使用string 对象,而是使用反序列化的实际XML 对象(无论是来自LINQ-to-XML 的XDocument 还是来自System.Xml 核心库的XmlDocument) .

      还有另一个问题展示了 Fluent Assertions 的功能,也展示了一些示例:Unit testing XML Generation

      【讨论】:

        【解决方案3】:

        test_xml 命名空间(XSD 和 XSI)位置与单元测试中的 control_xml 命名空间不匹配时遇到了同样的问题

        解决方案是XMLUnit.NET 2.x,它将 XML 比较为 XML 对象而不是字符串

        https://github.com/xmlunit/xmlunit.net

        使用流畅的 API:

        string String_Actual = serializadorAbstract.AsString;
        string String_Expected = File.ReadAllText(@"ExpectedOutput\Alumnos.xml");
        
        ISource control = Input.FromString(String_Expected).Build();
        ISource test = Input.FromString(String_Actual).Build();
        
        Diff differences = DiffBuilder.Compare(control).WithTest(test).Build();
        Assert.IsFalse(differences.HasDifferences());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-27
          • 2020-09-17
          • 1970-01-01
          • 2018-05-23
          • 2017-09-11
          • 2020-03-14
          • 2021-07-16
          • 2023-04-02
          相关资源
          最近更新 更多