简体   繁体   English

NUnit 3.0 和 Assert.Throws

[英]NUnit 3.0 and Assert.Throws

I am writing some unit tests with NUnit 3.0 and, unlike v2.x, ExpectedException() has been removed from the library.我正在使用 NUnit 3.0 编写一些单元测试,并且与 v2.x 不同,已从库中删除了ExpectedException()

Based on this answer, I can definitely see the logic in trying to catch specifically where in the test one expects their system to throw an exception (rather than just saying 'anywhere in the test').基于这个答案,我绝对可以看到试图在测试中具体捕捉到他们期望他们的系统抛出异常的地方的逻辑(而不仅仅是说“测试中的任何地方”)。

However, I tend to be very explicit about my Arrange, Act, and Assert steps and this makes it a challenge.然而,我倾向于对我的安排、行动和断言步骤非常明确,这使它成为一个挑战。

I used to do something like:我曾经做过类似的事情:

[Test, ExpectedException(typeof(FormatException))]
public void Should_not_convert_from_prinergy_date_time_sample1()
{
    //Arrange
    string testDate = "20121123120122";

    //Act
    testDate.FromPrinergyDateTime();

    //Assert
    Assert.Fail("FromPrinergyDateTime should throw an exception parsing invalid input.");
}

Now I need to do something like:现在我需要做类似的事情:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    //Arrange
    string testDate = "20121123120122";

    //Act/Assert
    Assert.Throws<FormatException>(() => testDate.FromPrinergyDateTime());
}

This isn't terrible, but muddies the Act and Assert, in my opinion.在我看来,这并不可怕,但会混淆 Act 和 Assert。 (Obviously, for this simple test, it's not hard to follow, but might be more challenging in larger tests). (显然,对于这个简单的测试,不难理解,但在更大的测试中可能更具挑战性)。

I've had a colleague suggest I get rid of Assert.Throws altogether and just do something like:我有一位同事建议我完全摆脱Assert.Throws并执行以下操作:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample3()
{
    //Arrange
    int exceptions = 0;
    string testDate = "20121123120122";

    //Act
    try
    {
        testDate.FromPrinergyDateTime();
    }
    catch (FormatException) { exceptions++;}

    //Assert
    Assert.AreEqual(1, exceptions);
}

Here, I stick with the strict AAA format, but at the expense of even more bloat.在这里,我坚持严格的 AAA 格式,但代价是更加臃肿。

So my question goes out to AAA-style testers: How would you do some sort of exception validation testing like I am trying to do here?所以我的问题是针对 AAA 风格的测试人员:您将如何进行某种异常验证测试,就像我在这里尝试做的那样?

I see where you're coming from, even though I don't mind combining Act/Assert steps in this case.我知道你来自哪里,即使我不介意在这种情况下结合行动/断言步骤。

The only thing I can think of is to store the actual delegate (here to FromPrinergyDateTime ) into a variable as the "act" step and then assert it:我唯一能想到的是将实际委托(这里是FromPrinergyDateTime )存储到一个变量中作为“行为”步骤,然后断言它:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    //Arrange
    string testDate = "20121123120122";

    //Act
    ActualValueDelegate<object> testDelegate = () => testDate.FromPrinergyDateTime();

    //Assert
    Assert.That(testDelegate, Throws.TypeOf<FormatException>());
}

I get that the "act" step isn't really acting, but rather defining what the action is.我明白“行动”步骤并不是真正的行动,而是定义行动是什么。 However, it does clearly delineate what action is being tested.但是,它确实清楚地描述了正在测试的操作。

In C# 7, there is another option (albeit very similar to the existing answers):在 C# 7 中,还有另一个选项(尽管与现有答案非常相似):

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    void CheckFunction()
    {
        //Arrange
        string testDate = "20121123120122";

        //Act
        testDate.FromPrinergyDateTime();
    }

    //Assert
    Assert.Throws(typeof(Exception), CheckFunction);
}

Blog post on the subject 关于该主题的博客文章

您可以在 NUnit 3 中创建自定义属性。这是如何创建[ExpectedException]属性的示例代码。(ExpectedExceptionExample 显示如何为 NUnit 实现自定义属性) https://github.com/nunit/nunit-csharp-samples

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM