NUnit期望例外

Mar*_*tin 51 c# teamcity continuous-integration nunit

我有一组测试用例,其中一些预计会抛出异常.因此,我已经设置了这些测试的属性,以期望这样的异常:

[ExpectedException("System.NullReferenceException")]
Run Code Online (Sandbox Code Playgroud)

当我在本地运行测试时,一切都很好.但是,当我将测试移至运行TeamCity的CI服务器时,所有具有预期异常的测试都会失败.这是一个已知的错误.

我知道NUnit还提供了一些Assert.Throws<>Assert.Throws方法.

我的问题是如何使用这些而不是我目前使用的属性?

我已经浏览了StackOverflow并尝试了一些似乎对我没用的东西.

有一个简单的1行解决方案来使用它吗?

Mar*_*off 92

我不确定你尝试过什么会给你带来麻烦,但是你可以简单地传入一个lambda作为Assert.Throws的第一个参数.这是我通过的一项测试中的一项:

Assert.Throws<ArgumentException>(() => pointStore.Store(new[] { firstPoint }));
Run Code Online (Sandbox Code Playgroud)

好的,这个例子可能有点冗长.假设我有一个测试

[Test]
[ExpectedException("System.NullReferenceException")]
public void TestFoo()
{
    MyObject o = null;
    o.Foo();
}
Run Code Online (Sandbox Code Playgroud)

会正常传递,因为o.Foo()会引发空引用异常.

然后,您将删除该ExpectedException属性并将您的呼叫包装o.Foo()在一个Assert.Throws.

[Test]
public void TestFoo()
{
    MyObject o = null;
    Assert.Throws<NullReferenceException>(() => o.Foo());
}
Run Code Online (Sandbox Code Playgroud)

Assert.Throws"尝试调用代表作为委托的代码片段,以验证它是否会抛出特定异常." 的() => DoSomething()语法表示的λ,基本上匿名方法.所以在这种情况下,我们告诉Assert.Throws你执行代码片段o.Foo().

所以不,你不只是像你做一个属性一样添加一行; 你需要在调用中显式地包装将抛出异常的测试部分Assert.Throws.你不一定要使用lambda,但这通常是最方便的.

  • 谢谢!它解决了我的问题。另外,如果 o.Foo 是可等待的,你应该使用 `Assert.Throws&lt;NullReferenceException&gt;(async () =&gt; await o.Foo())` 代替。 (2认同)
  • 完善.很棒的解释! (2认同)

Jer*_*ing 11

这是一个使用两种方式的简单示例.

string test = null;
Assert.Throws( typeof( NullReferenceException ), () => test.Substring( 0, 4 ) );
Assert.Throws<NullReferenceException>( () => test.Substring( 0, 4 ) );
Run Code Online (Sandbox Code Playgroud)

如果你不想使用lambdas.

[Test]
public void Test()
{
    Assert.Throws<NullReferenceException>( _TestBody );
}

private void _TestBody()
{
    string test = null;
    test.Substring( 0, 4 );
}
Run Code Online (Sandbox Code Playgroud)