格式十进制扩展的NUnit测试中的实际值和期望值不相同

本文关键字:期望值 扩展 十进制 NUnit 测试 格式 | 更新日期: 2023-09-27 18:08:47

我编写了以下扩展方法:

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"
  --------------^

格式十进制扩展的NUnit测试中的实际值和期望值不相同

您的问题确实来自于数字格式的不同空间表示。你遇到麻烦的空间是在NumberFormatInfo类的CurrencyGroupSeparator属性中定义的。如果使用以下代码段

检查标准ASCII空间和货币组分隔符空间的字符代码
Console.WriteLine("Space code: {0}", (Int32)' ');
var separator = Thread.CurrentThread.CurrentCulture.NumberFormat
    .CurrencyGroupSeparator;
Console.WriteLine("Currency separator code: {0}", (Int32)separator[0]);

…你会发现它分别打印32160。这就是字符串比较失败的原因。

为了进行单元测试,您可以将分隔符设置为实际的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,使用一些众所周知且易于验证的区域性设置(甚至可以修复空格以使其更容易):

[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);
}

在实际的应用程序中,您只需使用无区域性重载,并让区域性从用户当前设置中获取。