如何在 .NET 的单个单元测试中修改区域小数分隔符?

rac*_*cad 3 .net c# vb.net locale unit-testing

在 .NET(VB 或 C#)中并用于Microsoft.VisualStudio.TestTools.UnitTesting单元测试:

如何在单元测试中本地有效地更改区域设置小数分隔符,以便String.Format("{0:0.0}", aDouble)(AFAIK 与区域设置相关)生成具有修改后的区域设置的字符串?

编辑:观察:我不是问如何输出具有特定区域设置的文本。我问如何在单元测试中更改区域设置的小数分隔符,以便模拟具有不同小数分隔符的系统中会发生的情况。 我不是从单元测试代码中调用 String.Format,而是从测试的功能中调用 String.Format。

附加信息:

我正在 VB 中创建一个 .NET 库,并且有一个类MyClassEncode(...)该类的函数将数字信息等写入文本。

该组件将在不同计算机可能具有不同“小数分隔符”(逗号或点)配置的环境中使用。然而,我的组件应该对此不敏感,这意味着它应该始终输出“点”(例如通过使用System.Globalization.CultureInfo.InvariantCulture格式化数字时使用)。

我想编写一个单元测试,以确保即使系统区域小数分隔符设置为“逗号”而不是“点”,编码功能也将继续工作。我做了一些研究并得出了这样的结论:

公共子 Encode_CultureWithCommaSeparator_OutputMatchesTemplate()
  ...
  Dim oldCulture = Threading.Thread.CurrentThread.CurrentCulture
  ' 使用“,”作为小数点分隔符的区域性
  Threading.Thread.CurrentThread.CurrentCulture = New Globalization.CultureInfo("es-ES")
  比较编码到模板(...)
  Threading.Thread.CurrentThread.CurrentCulture = oldCulture
结束子

CompareEncodedToTemplate函数将使用该MyClass.Encode方法将信息写入 a,然后将其与模板文本文件MemoryStream逐行进行比较,当它们不相等时测试将失败。

我想要“模拟”的是Encode当区域设置的小数分隔符与“点”不同时该函数将如何运行。显然我的测试功能没有按我的预期工作:

我在我设置的小数分隔符指向的计算机中运行了测试,并且测试成功,所以我认为“我的编码功能将按我想要的方式工作,因为测试通过了”。

然而,后来我在小数点分隔符设置为逗号的计算机上运行测试,测试失败了。我意识到这是因为按照我的逻辑,我在格式化双精度数时Encode错过了使用。InvariantCulture这意味着我的测试没有按预期工作,因为我应该能够在第一台计算机上检测到这种情况(因为这是我想创建测试的原因)。

先感谢您。

Jon*_*son 5

我的开发机器和我们的 CI 服务器都遇到了这个问题。我编写了以下结构来提供帮助:

public struct CultureContext : IDisposable
{
    public static readonly CultureInfo CommaCulture = new CultureInfo("en-us")
    {
        NumberFormat =
        {
            CurrencyDecimalSeparator = ",",
            NumberDecimalSeparator = ",",
            PercentDecimalSeparator = ","
        }
    };

    public static readonly CultureInfo PointCulture = new CultureInfo("en-us")
    {
        NumberFormat =
        {
            CurrencyDecimalSeparator = ".",
            NumberDecimalSeparator = ".",
            PercentDecimalSeparator = "."
        }
    };

    private readonly CultureInfo _originalCulture;

    public CultureContext(CultureInfo culture)
    {
        _originalCulture = Thread.CurrentThread.CurrentCulture;
        Thread.CurrentThread.CurrentCulture = culture;
    }

    public void Dispose()
    {
        Thread.CurrentThread.CurrentCulture = _originalCulture;
    }

    public static void UnderBoth(Action test)
    {
        using (new CultureContext(PointCulture))
        {
            test();
        }

        using (new CultureContext(CommaCulture))
        {
            test();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以这样测试它:

CultureContext.UnderBoth(() => Assert.AreEqual("1.1", sut.ToString()));
Run Code Online (Sandbox Code Playgroud)