我怎样才能testing预期exception与Visual Studiotesting中的资源文件中的特定exception消息?

Visual Studio Test可以使用ExpectedException属性检查预期的exception。 你可以传入这样的exception:

[TestMethod] [ExpectedException(typeof(CriticalException))] public void GetOrganisation_MultipleOrganisations_ThrowsException() 

您也可以像这样检查ExpectedException中包含的消息:

 [TestMethod] [ExpectedException(typeof(CriticalException), "An error occured")] public void GetOrganisation_MultipleOrganisations_ThrowsException() 

但是在testingI18N应用程序时,我会使用资源文件来获取错误消息(如果需要,甚至可能决定testing错误消息的不同本地化版本,但Visual Studio不会让我这样做:

 [TestMethod] [ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)] public void GetOrganisation_MultipleOrganisations_ThrowsException() 

编译器会出现以下错误:

一个属性参数必须是一个常量expression式,一个属性的typeofexpression式或数组创buildexpression式

有谁知道如何testing从资源文件中有消息的exception?


我考虑的一个select是使用自定义的exception类,但基于经常听到的build议,如:

“如果你有一个错误条件,可以以不同于其他现有的exception的方式进行编程处理,那么就创build并抛出自定义的exception,否则就抛出一个现有的exception。 资源

我不希望在正常stream程中以不同的方式处理exception(这是一个严重的例外,所以我会进入恐慌模式),我不认为为每个testing用例创build例外是正确的。 有什么意见?

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

  • 是testing的一部分,在这种情况下,从资源中获取资源将是“错误的”(否则最终可能会导致资源严重受损),因此只要在更改资源时更新testing(或者testing失败)
  • 不是testing的一部分,你应该只关心它抛出exception。

请注意,第一个选项应该让你testing多种语言,给定以区域设置运行的能力。

至于多个例外情况,我来自C ++领域,那里可以接受(如果不常见的话)创build负载和大量exception(对于每个“throw”语句的一个点),但.Net的元数据系统可能不会不那样,所以这个build议。

我会build议使用辅助方法,而不是一个属性。 像这样的东西:

 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; } } 

然后你可以写下你的testing:

 [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); } 

这也有一个好处,它validationexception是抛出在你所期望的,而不是在你的testing方法的任何地方抛出的行。

ExpectedException消息参数与exception消息不匹配。 相反,如果预期的exception事实上没有发生,则这是打印在testing结果中的消息。

我想你可以在你的testing代码中做一个明确的try-catch,而不是依靠ExpectedException属性来为你做。 然后你可以想出一些帮助方法,它将读取资源文件,并将错误信息与发生exception的错误信息进行比较。 (当然,如果没有例外,那么testing用例应该被认为是失败的)

如果您切换到使用非常好的xUnit.Nettesting库,您可以用这样的东西replace[ExpectedException]:

 [Fact] public void TestException() { Exception ex = Record.Exception(() => myClass.DoSomethingExceptional()); // Assert whatever you like about the exception here. } 

我想知道NUnit是否正在从简单的道路上走下去……但是在这里你走了。

ExpectedException属性的新增function(2.4.3及以上版本)允许您通过Handler方法更多地控制对预期exception执行的检查 。 更多关于NUnit官方文档页面的详细信息。

 [ExpectedException( Handler="HandlerMethod" )] public void TestMethod() { ... } public void HandlerMethod( System.Exception ex ) { ... } 

注意:这里有什么感觉不对..为什么你的exception消息是国际化的?你是否在使用例外情况下需要处理或通知给用户。 除非你有一大堆文化多样的开发人员修复错误..你不应该需要这个。 英文或共同接受的语言的例外就足够了。 但万一你必须有这个..其可能:)

我遇到这个问题,试图自己解决类似的问题。 (我将在下面详细解释我所解决的问题。)

我不得不同意Gishu关于将exception消息国际化为代码异味的评论。

我最初在自己的项目中完成了这个工作,以便在我的应用程序和unit testing中抛出的错误消息之间保持一致。 即只需要在一个地方定义exception消息,Resource文件似乎是一个明智的做法,因为我已经将它用于各种标签和string了(因为添加引用是有意义的在我的testing代码中,以validation那些相同的标签显示在适当的地方)。

在某一时刻,我曾经考虑(并testing过)使用try / catch块来避免ExpectedException属性需要一个常量,但是如果大规模应用这样的话,似乎会导致相当多的额外代码。

最后,我解决的解决scheme是在我的资源库中创build一个静态类,并在那里存储我的exception消息。 这样就没有必要将它们国际化(我同意这一点是没有意义的),并且随时可以访问资源string,因为它们在同一个命名空间中。 (这符合我不希望validationexception文本的复杂过程。)

我的testing代码,然后简单归结为(原谅捣毁…):

 [Test, ExpectedException(typeof(System.ArgumentException), ExpectedException=ProductExceptionMessages.DuplicateProductName)] public void TestCreateDuplicateProduct() { _repository.CreateProduct("TestCreateDuplicateProduct"); _repository.CreateProduct("TestCreateDuplicateProduct"); }