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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9417213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 07:19:40  来源:igfitidea点击:

C#: How do I check "no exception occurred" in my MSTest unit test?

c#unit-testingexceptionmstest

提问by CuriousGeorge

I'm writing a unit test for this one method which returns "void". I would like to have one case that the test passes when there is no exception thrown. How do I write that in C#?

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

Assert.IsTrue(????)

(My guess is this is how I should check, but what goes into "???")

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

I hope my question is clear enough.

我希望我的问题足够清楚。

采纳答案by Rob Levine

Your unit test will fail anyway if an exception is thrown - you don't need to put in a special assert.

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

This is one of the few scenarios where you will see unit tests with no assertions at all - the test will implicitly fail if an exception is raised.

这是您将看到根本没有断言的单元测试的少数场景之一 - 如果引发异常,测试将隐式失败。

However, if you really did want to write an assertion for this - perhaps to be able to catch the exception and report "expected no exception but got this...", you can do this:

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

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

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

(the above is an example for NUnit, but the same holds true for MSTest)

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

回答by k.m

Don't test that something doesn't happen. It's like assuring that code doesn't break. That's sort of implied, we all strive for non-breaking, bug-less code. You want to write tests for that? Why just one method? Don't you want all your methods being tested that they don't throw some exception? Following that road, you'll end up with one extra, dummy, assert-less testfor every method in your code base. It brings no value.

不要测试某事不会发生。这就像确保代码不会中断。这有点暗示,我们都在努力实现不间断、无错误的代码。你想为此编写测试吗?为什么只有一种方法?难道你不希望你的所有方法都经过测试,它们不会抛出一些异常吗?沿着这条路走下去,您最终会得到一个额外的、虚拟的、无断言的测试,用于您的代码库中的每个方法。它没有带来任何价值。

Of course, if your requirement is to verify method doescatch exceptions, you do test that (or reversing it a bit; test that it does not throw what it is supposed to catch).

当然,如果您的要求是验证方法确实捕获了异常,您可以测试它(或稍微反转它;测试它不会抛出它应该捕获的东西)。

However, the general approach/practices remain intact - you don't write tests for some artificial/vague requirements that are out of scope of tested code (and testing that "it works" or "doesn't throw" is usually an example of such - especially in scenario when method's responsibilities are well known).

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

To put it simple - focus on what your code has to doand test for that.

简而言之 - 专注于您的代码必须执行的操作并对其进行测试。

回答by Clarkeye

In NUnit, you can use:

在 NUnit 中,您可以使用:

Assert.DoesNotThrow(<expression>); 

to assert that your code does not throw an exception. Although the test would fail if an exception is thrown even if there was no Assert around it, the value of this approach is that you can then distinguish between unmet expectations and bugs in your tests, and you have the option of adding a custom message that will be displayed in your test output. A well-worded test output can help you locate errors in your code that have caused a test to fail.

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

I think it's valid to add tests to ensure that your code is not throwing exceptions; for example, imagine you are validating input and need to convert an incoming string to a long. There may be occasions when the string is null, and this is acceptable, so you want to ensure that the string conversion does not throw an exception. There will therefore be code to handle this occasion, and if you haven't written a test for it you will be missing coverage around an important piece of logic.

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

回答by JJS

This helper class scratched my itch with MSTest. Maybe it can scratch yours also.

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

回答by jleach

I like to see an Assert.Whateverat the end of each test, just for consistency... without one, can I really be sure there's not supposed to be one there?

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

For me, this is as simple as putting Assert.IsTrue(true);

对我来说,这就像放置一样简单 Assert.IsTrue(true);

I knowI didn't accidentallyput that code in there, and thus I should be confident enough at quick a skim through that this was as intended.

知道我没有不小心把代码放在那里,因此我应该有足够的信心快速浏览一下,这符合预期。

    [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

    }

回答by Jess

My friend Tim told me about ExpectedException. I really like this b/c it is more succinct, less code, and very explicit that you are testing for an exception.

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

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

You can read way more about it here: ExpectedException Attribute Usage.

您可以在此处阅读更多相关信息:ExpectedException Attribute Usage