NUnit 的 ExpectedExceptionAttribute 是测试某些内容是否引发异常的唯一方法吗?

发布于 2024-07-08 10:41:30 字数 988 浏览 6 评论 0原文

我对 C# 和 NUnit 完全陌生。

在 Boost.Test 中有一系列 BOOST_*_THROW 宏。 在Python的测试模块中有TestCase.assertRaises方法。

据我了解,在带有 NUnit (2.4.8) 的 C# 中,进行异常测试的唯一方法是使用 ExpectedExceptionAttribute

为什么我应该更喜欢 ExpectedExceptionAttribute 而不是 - 比方说 - Boost.Test 的方法? 这个设计决策背后的推理是什么? 为什么 C# 和 NUnit 更好?

最后,如果我决定使用ExpectedExceptionAttribute,在引发并捕获异常后如何进行一些额外的测试? 假设我想测试要求,即在某些 setter 引发 System.IndexOutOfRangeException 后该对象必须有效。 您将如何修复以下代码以按预期编译和工作?

[Test]
public void TestSetterException()
{
    Sth.SomeClass obj = new SomeClass();

    // Following statement won't compile.
    Assert.Raises( "System.IndexOutOfRangeException",
                   obj.SetValueAt( -1, "foo" ) );

    Assert.IsTrue( obj.IsValid() );
}

编辑:感谢您的回答。 今天,我发现了一个这是测试 博客条目其中提到了您描述的所有三种方法(以及一个较小的变化)。 很遗憾我之前找不到它:-(。

I'm completely new at C# and NUnit.

In Boost.Test there is a family of BOOST_*_THROW macros. In Python's test module there is TestCase.assertRaises method.

As far as I understand it, in C# with NUnit (2.4.8) the only method of doing exception test is to use ExpectedExceptionAttribute.

Why should I prefer ExpectedExceptionAttribute over - let's say - Boost.Test's approach? What reasoning can stand behind this design decision? Why is that better in case of C# and NUnit?

Finally, if I decide to use ExpectedExceptionAttribute, how can I do some additional tests after exception was raised and catched? Let's say that I want to test requirement saying that object has to be valid after some setter raised System.IndexOutOfRangeException. How would you fix following code to compile and work as expected?

[Test]
public void TestSetterException()
{
    Sth.SomeClass obj = new SomeClass();

    // Following statement won't compile.
    Assert.Raises( "System.IndexOutOfRangeException",
                   obj.SetValueAt( -1, "foo" ) );

    Assert.IsTrue( obj.IsValid() );
}

Edit: Thanks for your answers. Today, I've found an It's the Tests blog entry where all three methods described by you are mentioned (and one more minor variation). It's shame that I couldn't find it before :-(.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小…红帽 2024-07-15 10:41:30

我很惊讶我还没有看到这种模式被提及。 David Arno 的非常相似,但我更喜欢它的简单性:

try
{
    obj.SetValueAt(-1, "foo");
    Assert.Fail("Expected exception");
}
catch (IndexOutOfRangeException)
{
    // Expected
}
Assert.IsTrue(obj.IsValid());

I'm surprised I haven't seen this pattern mentioned yet. David Arno's is very similar, but I prefer the simplicity of this:

try
{
    obj.SetValueAt(-1, "foo");
    Assert.Fail("Expected exception");
}
catch (IndexOutOfRangeException)
{
    // Expected
}
Assert.IsTrue(obj.IsValid());
恰似旧人归 2024-07-15 10:41:30

如果您可以使用 NUnit 2.5,那里有一些不错的帮助器

Assert.That( delegate { ... }, Throws.Exception<ArgumentException>())

If you can use NUnit 2.5 there's some nice helpers there.

Assert.That( delegate { ... }, Throws.Exception<ArgumentException>())
陪我终i 2024-07-15 10:41:30

MbUnit 语法是

Assert.Throws<IndexOutOfRangeException>(delegate {
    int[] nums = new int[] { 0, 1, 2 };
    nums[3] = 3;
});

The MbUnit syntax is

Assert.Throws<IndexOutOfRangeException>(delegate {
    int[] nums = new int[] { 0, 1, 2 };
    nums[3] = 3;
});
眼泪都笑了 2024-07-15 10:41:30

您的首选语法:

Assert.Raises( "System.IndexOutOfRangeException",
               obj.SetValueAt( -1, "foo" ) );

无论如何都无法使用 C# - obj.SetValueAt 将被评估并将结果传递给 Assert.Raises。 如果 SetValue 抛出异常,那么您将永远不会进入 Assert.Raises。

您可以编写一个辅助方法来执行此操作:

void Raises<T>(Action action) where T:Exception {
   try {
      action();
      throw new ExpectedException(typeof(T));
   catch (Exception ex) {
      if (ex.GetType() != typeof(T)) {
         throw;
      }
   }
}

它允许类似的语法:

Assert.Raises<System.IndexOutOfRangeException>(() => 
  obj.SetValueAt(-1, "foo")
;

Your preferred syntax:

Assert.Raises( "System.IndexOutOfRangeException",
               obj.SetValueAt( -1, "foo" ) );

woiuldn't work with C# anyway - the obj.SetValueAt would be evaluated and the result passed to Assert.Raises. If SetValue throws an exception, then you'd never get into Assert.Raises.

You could write a helper method to do it:

void Raises<T>(Action action) where T:Exception {
   try {
      action();
      throw new ExpectedException(typeof(T));
   catch (Exception ex) {
      if (ex.GetType() != typeof(T)) {
         throw;
      }
   }
}

Which allows the similar syntax of:

Assert.Raises<System.IndexOutOfRangeException>(() => 
  obj.SetValueAt(-1, "foo")
;
も让我眼熟你 2024-07-15 10:41:30

我一直采用以下方法:

bool success = true;
try {
    obj.SetValueAt(-1, "foo");
} catch () {
    success = false;
}

assert.IsFalse(success);

...

I've always adopted the following approach:

bool success = true;
try {
    obj.SetValueAt(-1, "foo");
} catch () {
    success = false;
}

assert.IsFalse(success);

...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文