Я понял. И да, это баг.
Проблема в том, что здесь происходит два уровня string.Format
.
Первый уровень форматирования что - то вроде:
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
Затем мы используем string.Format
с указанными вами параметрами:
string finalMessage = string.Format(template, parameters);
(Очевидно, есть культура и какая- то санитарная обработка ... но этого недостаточно.)
Это выглядит нормально - если только ожидаемые и фактические значения сами по себе не заключаются в фигурные скобки после преобразования в строку, для чего они и используются Size
. Например, ваш первый размер будет преобразован в:
{Width=0, Height=0}
Итак, второй уровень форматирования выглядит примерно так:
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
... и вот что не получается. Ой.
Действительно, мы можем очень легко доказать это, обманув форматирование, чтобы использовать наши параметры для ожидаемой и фактической частей:
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
Результат:
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
Явно сломан, как мы и не ожидали, и foo
не было реальной стоимости bar
!
В основном это похоже на атаку с использованием SQL-инъекций, но в менее пугающем контексте string.Format
.
В качестве обходного пути вы можете использовать, string.Format
как предлагает StriplingWarrior. Это позволяет избежать выполнения второго уровня форматирования результата форматирования с использованием фактических / ожидаемых значений.
Assert.AreEqual(struct1, struct2, string.Format("Failed expected {0} actually is {1}
, struct1.ToString (), struct2.ToString ())) `?