【问题标题】:String comparison assertion failing when it looks like it should pass字符串比较断言在看起来应该通过时失败
【发布时间】:2014-01-28 00:35:15
【问题描述】:

我有一个检查项目是否正确序列化的测试

public interface IMyJsIdentity
{
    string Forename { get; }
    string Surname { get; }
    string Guid { get; }                 
}

public class MyIdentity : IMyJsIdentity
{
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Guid { get; set; }
    public int Id { get; set; }
}

[Fact]
public void SerialiseCorrectly()
{
    // Arrange
    MyIdentity identity = new MyIdentity()
    {
        Forename = "forename",
        Surname = "surname",
        Guid = "abcdefghijk"
    };

    // Act
    string result = JsonConvert.SerializeObject(
        identity, 
        new JsonSerializerSettings()
        {
            ContractResolver = new InterfaceContractResolver(typeof(IMyJsIdentity))
        });

    // Assert
    result.Should().Be(
        "{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}"
        );
}

但是我在测试失败时收到以下错误

Xunit.Sdk.AssertException: Expected string to be 
"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}" with a length of 66, but 
"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}" has a length of 64.

Json.net 显然对字符串做了一些特别的事情,但我不知道是什么。

奇怪的是通过了

result.Should().Be(
    String.Format("{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}")
    );

我想这没什么大不了的,但我想知道为什么。

【问题讨论】:

  • 尝试调试它并查看两个字符串的内部 char 数组,这可能会让您知道可能出了什么问题。
  • 我想问题出在你的 '.Should().Be()' 方法上。这些字符串的长度完全相同,但报告它们不同。可能是因为较长的那个算引号?
  • 有任何理由拥有双 {{}}?如果在某个地方对该字符串进行了String.Format 调用,它会将它们转换为单个花括号。这也可能是输出消息/错误中的一些错误信息,放置了额外的花括号。编辑:同样,如果您不使用String.Format 调用,那么双括号根本不能用作转义字符,除非您打算使用 2 个大括号,否则不应将它们加倍。

标签: c# json.net string-comparison xunit fluent-assertions


【解决方案1】:

我刚刚测试,result的值为:

{"Forename":"forename","Surname":"surname","Guid":"abcdefghijk","Id":0}

这自然会与您预期的字符串不符:

"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}"

使用双花括号是一种转义序列,仅适用于String.Format 方法中使用的格式字符串,因此您可以包含一个 大括号。来自Composite Formatting MSDN page

左大括号和右大括号被解释为开始和结束一个 格式项。因此,您必须使用转义序列来显示 文字左大括号或右大括号。指定两个左大括号 ("{{") 在固定文本中显示一个左大括号 ("{"),或两个 右大括号(“}}”)显示一个右大括号(“}”)。

如果您不使用String.Format,则双括号将按照C# Specification 2.4.4.5 的字面意思解释为两个大括号,因为它不是字符串文字的转义字符。

由此产生的错误消息令人困惑。我不确定这是因为调试器如何将其报告给 GUI,还是因为它们如何格式化错误消息(可能它们过于激进地转义输出大括号),或者是什么。

如果您将测试更改为:

result.Should().Be(
        "{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}"
        );

然后我怀疑它会通过。这由您使用 String.Format 调用的附加测试支持,该调用将您的双括号更改为单括号。现在,如果您打算在 JSON 周围使用双括号,这完全是另一个问题,但我怀疑这不是您的意图。

【讨论】:

  • 你说得对,谢谢。我陷入了让它失败的陷阱,然后只是将我的期望复制到测试失败窗口之外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 2015-09-02
  • 2016-07-05
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多