字符串比较断言看起来应该通过时失败

时间:2014-01-09 12:41:04

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

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

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\"}}")
    );

我想这不是什么大问题,但我想知道原因。

1 个答案:

答案 0 :(得分:4)

我刚刚测试过,result的值是:

  

{ “用名字”: “用名字”, “姓”: “姓”, “GUID”: “ABCDEFGHIJK”, “ID”:0}

对于您期望的字符串:

,这自然会失败
  

“{{\” 用名字\ “:\” 用名字\ “\ ”姓\“:\ ”姓\“,\ ”GUID \“:\ ”ABCDEFGHIJK \“}}”

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

  

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

如果你没有使用String.Format,那么根据C# Specification 2.4.4.5,双括号将按字面解释为两个括号,因为它不是字符串文字的转义字符。

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

如果您将测试更改为:

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

然后它会通过我怀疑。您可以使用String.Format调用进行额外测试,从而将双括号更改为单个括号。现在,如果你打算围绕你的JSON进行双重包裹,这完全是另一个问题,但我怀疑这不是你的意图。