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

时间:2012-02-23 16:39:23

标签: c# unit-testing exception mstest

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

Assert.IsTrue(????)

(我猜这是我应该检查的方式,但是“???”的内容是什么)

我希望我的问题很清楚。

7 个答案:

答案 0 :(得分:108)

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

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

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

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

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

(上面是NUnit的一个例子,但MSTest也是如此)

答案 1 :(得分:23)

在NUnit中,您可以使用:

Assert.DoesNotThrow(<expression>); 

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

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

答案 2 :(得分:11)

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

当然,如果您的要求是要验证方法是否捕获异常,那么您可以对其进行测试(或者将其反转一下;测试它不会抛出它应该抓住。)

然而,一般方法/实践保持不变 - 您不会为超出测试代码范围的某些人为/模糊要求编写测试(并且测试“它有效”或“不抛出”通常是这样的一个例子 - 特别是在方法的职责众所周知的情况下)。

简单来说 - 专注于您的代码必须执行的操作并对其进行测试。

答案 3 :(得分:5)

这个助手类用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);
        }
    }
}

答案 4 :(得分:2)

我喜欢在每次测试结束时看到Assert.Whatever,只是为了保持一致......没有一个,我真的可以肯定那里不应该有一个吗?

对我来说,这就像放Assert.IsTrue(true);

一样简单

知道我没有意外地将代码放在那里,因此我应该有足够的信心快速浏览一下这是否符合预期。

    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }

答案 5 :(得分:0)

另一种对我有用的方法是将其存储在变量中并检查输出。

var result = service.Run()
Assert.IsFalse(result.Errors.Any())

答案 6 :(得分:-1)

我的朋友Tim告诉了我 ExpectedException 。我真的很喜欢这个b / c,它更加简洁,更少的代码,并且非常明确地表明您正在测试异常。

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

您可以在这里详细了解它:ExpectedException Attribute Usage