如何使用Visual Studio Test中的资源文件中的特定异常消息测试预期的异常?

Ale*_*eby 39 unit-testing exception internationalization visual-studio

Visual Studio Test可以使用ExpectedException属性检查预期的异常.您可以传递这样的异常:

[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
Run Code Online (Sandbox Code Playgroud)

您还可以检查ExpectedException中包含的消息,如下所示:

[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
Run Code Online (Sandbox Code Playgroud)

但是在测试I18N应用程序时,我会使用资源文件来获取该错误消息(如果我愿意,任何人甚至可能决定测试错误消息的不同本地化,但Visual Studio不允许我这样做:

[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
Run Code Online (Sandbox Code Playgroud)

编译器将给出以下错误:

属性参数必须是属性的常量表达式,typeof表达式或数组创建表达式

有人知道如何测试具有资源文件消息的异常吗?


我考虑过的一个选项是使用自定义异常类,但基于经常听到的建议,例如:

"如果您有一个错误条件,可以以与任何其他现有异常不同的方式以编程方式处理,则创建并抛出自定义异常.否则,抛出一个现有异常." 资源

我不希望在正常流程中以不同方式处理异常(这是一个关键的例外,所以我无论如何都要进入恐慌模式)并且我认为为每个测试用例创建一个例外是不对的.任何意见?

Dan*_*ted 63

我建议使用辅助方法而不是属性.像这样的东西:

public static class ExceptionAssert
{
  public static T Throws<T>(Action action) where T : Exception
  {
    try
    {
      action();
    }
    catch (T ex)
    {
      return ex;
    }
    Assert.Fail("Exception of type {0} should be thrown.", typeof(T));

    //  The compiler doesn't know that Assert.Fail
    //  will always throw an exception
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以写下你的测试:

[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
  OrganizationList organizations = new Organizations();
  organizations.Add(new Organization());
  organizations.Add(new Organization());

  var ex = ExceptionAssert.Throws<CriticalException>(
              () => organizations.GetOrganization());
  Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,它可以验证异常是否在您希望抛出的行上而不是在测试方法中的任何位置抛出.


use*_*794 14

ExpectedException Message参数与异常消息不匹配.相反,如果预期的异常实际上没有发生,则这是在测试结果中打印的消息.


Sim*_*han 7

只是一个意见,但我会说错误文本:

  • 测试的一部分,在这种情况下,从资源获取它将是"错误的"(否则你可能最终得到一个受到严重破坏的资源),所以只需在更改资源时更新测试(或测试失败)
  • 不是测试的一部分,你应该只关心它抛出异常.

请注意,第一个选项应该允许您测试多种语言,因为它能够使用语言环境运行.

至于多个异常,我来自C++领域,在大型heirachies中创建加载和异常加载(到每个'throw'语句一个点!)是可以接受的(如果不常见),但是.Net的元数据系统可能没有不喜欢那样,因此这个建议.