C#:如何在单元测试中检查"没有发生异常"?

Cur*_*rge 75 c# unit-testing mstest exception

我正在为这个返回"void"的方法编写一个单元测试.我希望有一个案例,当没有异常抛出时,测试通过.我如何用C#编写?

Assert.IsTrue(????)
Run Code Online (Sandbox Code Playgroud)

(我猜这是我应该检查的,但是什么进入"???")

我希望我的问题很清楚.

Rob*_*ine 123

如果抛出异常,你的单元测试无论如何都会失败 - 你不需要输入特殊的断言.

这是少数情况下您将看到完全没有断言的单元测试的情况之一 - 如果引发异常,测试将隐式失败.

但是,如果你确实想要为此编写一个断言 - 也许是为了能够捕获异常并报告"预期没有例外但得到了这个......",你可以这样做:

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

(以上是NUnit的示例,但MSTest也是如此)

  • 只有在抛出未捕获的异常时,测试才会失败.依赖于异常处理程序中的代码,单元测试可能会通过. (7认同)

Cla*_*eye 23

在NUnit中,您可以使用:

Assert.DoesNotThrow(<expression>); 
Run Code Online (Sandbox Code Playgroud)

断言你的代码不会抛出异常.虽然如果抛出异常,即使周围没有Assert,测试也会失败,但这种方法的价值在于您可以区分测试中未满足的期望和错误,并且您可以选择添加自定义消息将显示在您的测试输出中.一个措辞良好的测试输出可以帮助您找到代码中导致测试失败的错误.

我认为添加测试以确保您的代码不会抛出异常是有效的; 例如,假设您正在验证输入并需要将传入的字符串转换为long.有时字符串为null,这是可以接受的,因此您需要确保字符串转换不会引发异常.因此会有代码来处理这种情况,如果你还没有为它编写测试,那么你将缺少一个重要逻辑的覆盖范围.

  • @DanCsharpster,我认为至少在 MSTest 中没有 - 当我过去在 MSTest 中需要此功能时,我做了这样的事情:`public class TestBase { //相信我,我不'我比你更不喜欢这个了。protected void AssertDoesNotThrow(Action 操作,字符串消息) { try { action(); } catch (异常) { Assert.Fail(消息); } } }` (2认同)

k.m*_*k.m 10

不要测试不会发生的事情.这就像确保代码不会破坏一样.这有点暗示,我们都在争取不破坏,无错误的代码.你想为此编写测试吗?为什么只有一种方法?难道您不希望所有方法都经过测试,他们不会抛出异常吗?在这条道路之后,您将最终为代码库中的每个方法进行一次额外的虚拟无断言测试.它没有任何价值.

当然,如果你的要求是验证方法确实捕获异常,你会测试(或者稍微反转一下;测试它不会抛出它应该捕获的内容).

然而,一般的方法/做法保持不变 - 你不写测试设置一些人工/含糊的要求是出的测试代码(范围和测试"它的工作原理"或"不投",是通常的例子这样 - 特别是在方法的职责众所周知的情况下).

简单来说 - 专注于你的代码必须做什么并测试它.

  • -1我可以想到需要的正功能和不抛出异常.对于一个方法,它的工作是处理异常,记录它们并采取行动 - 而不会进一步抛出异常.你提出了一个很好的一般观点 - 然后在_absolute中说话,好像它总是如此. (8认同)
  • downvote已被删除 - 下次我投票时我不会那么高兴! (4认同)
  • @RobLevine:我理解你的例子并且意识到你在这种情况下编写测试.然而,正如您所注意到的,我的观点确实是关于更一般的实践 - 可以说,测试您的代码应该做什么而不是测试您的代码不执行的操作.我稍微改写了一下帖子,以便我的观点更清晰,更接近我的想法.还让您有机会重新考虑投票.感谢您的澄清和抱歉延迟回复. (3认同)
  • 在我们的项目中,我们有htmlvalidator类,如果html无效则抛出异常.例如当用户输入(使用控制台)javascript在丰富的组合中.所以在我的案例代码中我的代码所做的是不抛出异常(白名单方法),我需要测试它. (2认同)
  • 不同意这个答案。有时在某种情况下测试某些东西是否缺失可能是一个有效的测试。 (2认同)

JJS*_*JJS 6

这个助手班用MSTest抓住了我的痒.也许它也会刮伤你的.

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();

    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 现在这已经非常旧了,但是 `Assert` 有一个单例属性访问器 `That`,可以将其用作扩展方法的挂钩。使用“Assert.That.DoesNotThrow()”而不是“AssertEx.DoesNotThrow()”可能更简洁、更容易发现。这只是一个意见。 (2认同)