Ich habe es. Und ja, es ist ein Fehler.
Das Problem ist, dass es hier zwei Ebenen gibt string.Format.
Die erste Formatierungsstufe ist wie folgt:
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
Dann verwenden wir string.Formatmit den von Ihnen angegebenen Parametern:
string finalMessage = string.Format(template, parameters);
(Offensichtlich werden Kulturen bereitgestellt und eine Art Desinfektion ... aber nicht genug.)
Das sieht gut aus - es sei denn, die erwarteten und tatsächlichen Werte selbst stehen nach der Konvertierung in eine Zeichenfolge in geschweiften Klammern - wofür sie dies tun Size. Zum Beispiel wird Ihre erste Größe konvertiert in:
{Width=0, Height=0}
Die zweite Formatierungsstufe ist also ungefähr so:
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
... und genau das scheitert. Autsch.
In der Tat können wir dies wirklich leicht beweisen, indem wir die Formatierung täuschen, um unsere Parameter für die erwarteten und tatsächlichen Teile zu verwenden:
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
Das Ergebnis ist:
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
Deutlich kaputt, da wir fooweder den tatsächlichen Wert erwartet hatten bar!
Im Grunde ist dies wie ein SQL-Injection-Angriff, aber in dem weniger beängstigenden Kontext von string.Format.
Als Problemumgehung können Sie verwenden, string.Formatwie von StriplingWarrior vorgeschlagen. Dadurch wird vermieden, dass die zweite Formatierungsstufe für das Ergebnis der Formatierung mit den tatsächlichen / erwarteten Werten ausgeführt wird.
Assert.AreEqual(struct1, struct2, string.Format("Failed expected {0} actually is {1}, struct1.ToString (), struct2.ToString ())) `?