Фактические и ожидаемые значения в тесте NUnit для расширения десятичного формата не совпадают - PullRequest
5 голосов
/ 14 сентября 2011

Я написал следующий метод расширения:

public static class DecimalExtensions
{
   public static string FormatCurrency(this decimal instance)
   {
      return string.Format("{0:c}", instance);
   }
}

Тест NUnit:

[TestFixture]
public class DecimalExtensionsTests
{
   [Test]
   public void Format_should_return_formatted_decimal_string()
   {
      // Arrange
      decimal amount = 1000;

      // Act
      string actual = amount.FormatCurrency();

      // Assert
      Assert.AreEqual("R 1 000,00", actual);
   }
}

Мой тест не пройден, и я не уверен, почему. Я получаю следующую ошибку:

String lengths are both 10. Strings differ at index 3.
  Expected: "R 1 000,00"
  But was:  "R 1 000,00"
  --------------^

1 Ответ

4 голосов
/ 21 апреля 2012

Ваша проблема действительно связана с различным пространственным представлением в числовом формате.Пространство, с которым у вас возникают проблемы, определяется в свойстве NumberFormatInfo class 'CurrencyGroupSeparator.Если вы проверите коды символов как стандартного пространства ASCII, так и пространства разделителя группы валют с помощью следующего фрагмента

Console.WriteLine("Space code: {0}", (Int32)' ');
var separator = Thread.CurrentThread.CurrentCulture.NumberFormat
    .CurrencyGroupSeparator;
Console.WriteLine("Currency separator code: {0}", (Int32)separator[0]);

... вы обнаружите, что он печатает 32 и 160 соответственно.Вот почему сравнение строк не удается.

В целях модульного тестирования вы можете установить разделитель на фактическое пространство ASCII, например так:

Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyGroupSeparator = " ";

Однако я бы советую против этого .Вам нужно подумать, что произойдет, когда разработчик с другими настройками культуры запустит ваш модульный тест.Скорее всего, это не удастся, так как результирующие строки могут отличаться.Чтобы сделать ваш метод более удобным ( и модульные тесты более изолированными ), просто добавьте перегрузку, которая принимает информацию о культуре:

public static string FormatCurrency(this decimal instance)
{
   return instance.FormatCurrency(Thread.CurrentThread.CultureInfo);
}

public static string FormatCurrency(this decimal instance, CultureInfo culture)
{
    return string.Format(culture, "{0:c}", instance);
}

В своем модульном тесте вы пишете тест по второму методу снекоторые общеизвестные и легко проверяемые параметры культуры (может даже исправить пространство, чтобы сделать его проще):

[Test]
public void FormatCurrency_should_return_formatted_decimal_string()
{
    decimal amount = 1000;
    var culture = CultureInfo.CreateSpecificCulture("en-us");
    // replacing space (160) with space (32)
    culture.NumberFormat.CurrencyGroupSeparator = " ";

    // Act
    string actual = amount.FormatCurrency(culture);

    // Assert
    Assert.AreEqual("$1 000.00", actual);
}

И в своем реальном приложении вы просто используете перегрузку без учета культуры и позволяете культуре быть единственнойиз текущих настроек пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...