You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多语言构建服务器下如何断言异常消息(MsTest v2+FluentAssertions)

解决多语言环境下异常消息的单元测试问题

针对你的场景,有几个更优雅的解决方案,避免硬编码多语言消息判断:

方案1:强制测试线程使用英文区域设置

异常消息的语言通常由CurrentUICulture决定,而非仅CurrentCulture。你之前只设置了CurrentCulture,需要同时设置两者为英文区域:

方法1:在测试方法内直接设置

[TestMethod]
public void TestMethodThatThrows()
{
    // 保存原区域设置,测试后恢复(可选但推荐)
    var originalCulture = Thread.CurrentThread.CurrentCulture;
    var originalUiCulture = Thread.CurrentThread.CurrentUICulture;
    try
    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

        var sut = new ObjectWithMethodThatThrows();
        Action act = () => sut.MethodThatThrows(null);
        act.Should().Throw<ArgumentNullException>().WithMessage("*Value cannot be null*");
    }
    finally
    {
        Thread.CurrentThread.CurrentCulture = originalCulture;
        Thread.CurrentThread.CurrentUICulture = originalUiCulture;
    }
}

方法2:在测试类初始化/清理中全局设置

如果多个测试都需要,可在测试类的初始化方法中统一设置,避免重复代码:

[TestClass]
public class YourTestClass
{
    private CultureInfo _originalCulture;
    private CultureInfo _originalUiCulture;

    [TestInitialize]
    public void TestInitialize()
    {
        _originalCulture = Thread.CurrentThread.CurrentCulture;
        _originalUiCulture = Thread.CurrentThread.CurrentUICulture;
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
    }

    [TestCleanup]
    public void TestCleanup()
    {
        Thread.CurrentThread.CurrentCulture = _originalCulture;
        Thread.CurrentThread.CurrentUICulture = _originalUiCulture;
    }

    [TestMethod]
    public void TestMethodThatThrows()
    {
        var sut = new ObjectWithMethodThatThrows();
        Action act = () => sut.MethodThatThrows(null);
        act.Should().Throw<ArgumentNullException>().WithMessage("*Value cannot be null*");
    }
}

方案2:验证异常的参数名而非消息文本

对于ArgumentNullException这类有明确属性的异常,直接验证ParamName比验证消息更可靠,完全不受语言环境影响:

[TestMethod]
public void TestMethodThatThrows()
{
    var sut = new ObjectWithMethodThatThrows();
    Action act = () => sut.MethodThatThrows(null);
    act.Should().Throw<ArgumentNullException>()
       .WithParameterName("arg");
}

FluentAssertions的WithParameterName方法专门用于验证ArgumentNullException的ParamName属性,无需关心消息语言。

方案3:使用FluentAssertions的自定义消息匹配逻辑(备选)

如果确实需要验证消息内容,可预定义多语言消息集合,用Or组合断言:

[TestMethod]
public void TestMethodThatThrows()
{
    var expectedMessages = new[] { "*Value cannot be null*", "*La valeur ne peut pas être null.*" };
    var sut = new ObjectWithMethodThatThrows();
    Action act = () => sut.MethodThatThrows(null);
    act.Should().Throw<ArgumentNullException>()
       .Which.Message.Should().MatchAny(expectedMessages);
}

不过这个方案不如前两个优雅,仅推荐在无法使用前两种方案的场景下使用。

内容的提问来源于stack exchange,提问作者bkqc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:30:13