如何在 dotnetcore xunit 测试中设置区域性

问题描述 投票:0回答:3

我有以下单元测试,正在从 .Net Framework 库移植到 .Net core xunint 测试库。需要添加单元测试的项目是

https://github.com/dotliquid/dotliquid

并且正在添加到所选文件中,如下所示

我要添加的单元测试是

[Test]
public void ParsingWithCommaDecimalSeparatorShouldWork()
{
    var ci = new CultureInfo(CultureInfo.CurrentCulture.Name)
             {
                 NumberFormat =
                 {
                     NumberDecimalSeparator = ","
                     , NumberGroupSeparator = "."
                 }
             };
    Thread.CurrentThread.CurrentCulture = ci;

    var t = Template.Parse("{{2.5}}");
    var result = t.Render( new Hash(), CultureInfo.InvariantCulture );
    Assert.AreEqual( result, "2.5"   );
}

但是测试在 dotnet core 中编译失败。

严重性代码描述项目文件行抑制状态 错误 CS1061“线程”不包含定义 “CurrentCulture”并且没有扩展方法“CurrentCulture”接受 可以找到“Thread”类型的第一个参数(您是否缺少 using 指令或程序集 参考?)DotLiquid.Tests(net451) C:\Users\phelan\workspace\dotliquid\src\DotLiquid.Tests\OutputTests.cs 113 N/A

我需要对不同的文化进行不同的单元测试。我想创建一个 XUnit 理论,其中每个实例都传递不同的文化,以便单元测试进行验证。在 .NetCore 中这是如何完成的?

c# .net-core cultureinfo xunit
3个回答
11
投票

我查看了一些 dotnet source,然后发现了这个。

CultureInfo.DefaultThreadCurrentCulture = ci;

基本上看起来您可以从

CultureInfo
的静态属性设置默认线程当前区域性,而不是从
Thread.CurrentThread

再探索一下,我发现了这个

public CultureInfo CurrentCulture
{
    get
    {
        Contract.Ensures(Contract.Result<CultureInfo>() != null);
        return CultureInfo.CurrentCulture;
    }

    set
    {
        Contract.EndContractBlock();

        // If you add more pre-conditions to this method, check to see if you also need to 
        // add them to CultureInfo.DefaultThreadCurrentCulture.set.

        if (m_CurrentCulture == null && m_CurrentUICulture == null)
            nativeInitCultureAccessors();

        CultureInfo.CurrentCulture = value;
    }
}

这是在

Thread.cs
。因此您可以显式设置
CultureInfo.CurrentCulture
属性。

示例:

CultureInfo.CurrentCulture = new CultureInfo("en-GB"); ;

Assert.Equal("£1,000.00", String.Format("{0:C}", 1000));

CultureInfo.CurrentCulture = new CultureInfo("en-US"); ;

Assert.Equal("$1,000.00", String.Format("{0:C}", 1000));

单元测试项目的csproj文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp1.0</TargetFramework>

    <IsPackable>false</IsPackable>

    <ApplicationIcon />

    <OutputType>Library</OutputType>

    <StartupObject />
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170425-07" />
    <PackageReference Include="xunit" Version="2.2.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
  </ItemGroup>

</Project>

0
投票

解决办法是设置

CultureInfo.DefaultThreadCurrentCulture = ci;

然后然后启动一个新线程。这将为下一个线程设置当前区域性。最终的测试用例是。

[Test]
public void ParsingWithCommaDecimalSeparatorShouldWork()
{
    var ci = new CultureInfo(CultureInfo.CurrentCulture.Name)
             {
                 NumberFormat =
                 {
                     NumberDecimalSeparator = ","
                     , NumberGroupSeparator = "."
                 }
             };

    CultureInfo.DefaultThreadCurrentCulture = ci;
    var result = "";
    var thread = new Thread
        ( delegate()
        {
            Console.WriteLine(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
            Console.WriteLine(CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator);

            var t = Template.Parse("{{2.5}}");
            result = t.Render(new Hash(), CultureInfo.InvariantCulture);
        } );
    thread.Start();
    thread.Join();
    Assert.AreEqual(result, "2.5");

}

虽然有点乱,但还是能完成工作。


0
投票

XUnit 示例项目展示了一种使用属性为给定事实设置区域性的巧妙方法:https://github.com/xunit/samples.xunit/tree/main/UseCulture

[Fact, UseCulture("nb-NO")]
public void AttributeChangesCultureToNorwegianInTestMethod()
{
    Assert.Equal("nb-NO", Thread.CurrentThread.CurrentCulture.Name);
    Assert.Equal("nb-NO", Thread.CurrentThread.CurrentUICulture.Name);
}

我希望他们对这种方法有原生支持,但你必须从他们的示例项目中实现/复制

UseCultureAttribute

© www.soinside.com 2019 - 2024. All rights reserved.