Lo tengo. Y sí, es un error.
El problema es que hay dos niveles de string.Formatacción aquí.
El primer nivel de formateo es algo como:
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
Luego usamos string.Formatcon los parámetros que ha proporcionado:
string finalMessage = string.Format(template, parameters);
(Obviamente, se están proporcionando cultivos y algún tipo de desinfección ... pero no lo suficiente).
Eso se ve bien, a menos que los valores esperados y reales terminen con llaves, después de convertirse en una cadena, para lo cual sirven Size. Por ejemplo, su primer tamaño termina convirtiéndose en:
{Width=0, Height=0}
Entonces, el segundo nivel de formato es algo como:
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
... y eso es lo que falla. Ay.
De hecho, podemos probar esto muy fácilmente engañando al formato para que use nuestros parámetros para las partes esperadas y reales:
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
El resultado es:
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
Claramente roto, ya que no lo esperábamos fooni el valor real bar.
Básicamente, esto es como un ataque de inyección SQL, pero en el contexto bastante menos aterrador de string.Format.
Como solución alternativa, puede utilizarlo string.Formatcomo sugiere StriplingWarrior. Eso evita que se realice el segundo nivel de formateo en el resultado del formateo con los valores reales / esperados.
Assert.AreEqual(struct1, struct2, string.Format("Failed expected {0} actually is {1}, struct1.ToString (), struct2.ToString ())) `?