我写了下面的扩展方法:
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"
--------------^
最佳答案
您的问题确实来自数字格式的不同空间表示。 NumberFormatInfo
中定义了您遇到问题的空间类' CurrencyGroupSeparator
属性(property)。如果您使用以下代码片段检查标准 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);
}
在您的实际应用程序中,您只需使用无文化重载,让文化成为用户当前设置的文化。
关于c# - 格式十进制扩展的 NUnit 测试中的实际值和预期值不相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7417948/