多语言构建服务器下如何断言异常消息(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
相关产品推荐
相关产品推荐

