Nunit 测试异常 - 如何测试 `ArgumentOutOfRangeException(paramName, message)`

问题描述 投票:0回答:2

有很多关于 Nunit 和测试异常的线程。但是,我无法弄清楚如何将其应用到我的特定代码上。该参数给我带来了一些麻烦。

我抛出的异常看起来像这样:

throw new ArgumentOutOfRangeException(paramName: nameof(valueMayNotBeZero), message: "The argument must have a positive value!");

非常感谢指导和评论。

我的问题

  • 还有哪些方法可以测试异常?
  • 根据您的经验,您有哪些最佳实践?

在此示例中,我创建一个异常对象并根据我的实际字符串检查属性

Message
。这似乎有点尴尬。但这是我运行测试的唯一方法。
var result = Assert.Throws<ArgumentOutOfRangeException>(() => testObject.ThrowAnException(valueMayNotBeZero));

Assert.That(result.Message, Is.EqualTo("The argument must have a positive value! (Parameter 'valueMayNotBeZero')"));

代码

Program.cs

using StackOverflow;

GenerateException demo = new();
try
{
    Console.WriteLine($"Value: {demo.ThrowAnException(1.5):f2}");

}
catch (Exception e)
{
    Console.WriteLine("Unexpected Exception!");
    Console.WriteLine(e);
}

Console.WriteLine($"\n***** Press ENTER To Continue *****");
Console.ReadLine();

GenerateException.cs

namespace StackOverflow;

public class GenerateException
{
    public double ThrowAnException(double valueMayNotBeZero)
    {
        if (valueMayNotBeZero <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(valueMayNotBeZero), "The argument must have a positive value!");
        }

        return valueMayNotBeZero;
    }
}

测试

GenerateExceptionTests.cs

using StackOverflow;

namespace SackOverflowTest;

public class GenerateExceptionTests
{
    private static IEnumerable<double> SourceProvider()
    {
        yield return 10.0;
        yield return 99.99;
    }

    private static IEnumerable<double> SourceProviderException()
    {
        // GrossSalary
        yield return 0.0;
        yield return -10.0;
    }

    [TestCaseSource(nameof(SourceProvider))]
    public void CreateNoExceptionTest(double valueMayNotBeZero)
    {
        // ***** Arrange *****
        GenerateException testObject = new();

        // ***** Act *****
        var result = testObject.ThrowAnException(valueMayNotBeZero);

        // ***** Assert *****
        Assert.That(result, Is.EqualTo(valueMayNotBeZero));
    }

    [TestCaseSource(nameof(SourceProviderException))]
    public void CreateAnExceptionTest(double valueMayNotBeZero)
    {
        // ***** Arrange *****
        GenerateException testObject = new();

        // ***** Act *****
        var result = Assert.Throws<ArgumentOutOfRangeException>(() => testObject.ThrowAnException(valueMayNotBeZero));

        // ***** Assert *****
        Assert.That(result.Message, Is.EqualTo("The argument must have a positive value! (Parameter 'valueMayNotBeZero')"));
        // somehow not working; logic error?
        //Assert.Throws<ArgumentOutOfRangeException>(() => BusinessMiniJob.CalculateEmployeeSalary(valueMayNotBeZero), "The argument must have a positive value!");
        //Assert.That(() => Throws.TypeOf<ArgumentOutOfRangeException>().And.Property(nameof(valueMayNotBeZero)).And.Message.Equals("The argument must have a positive value!"));
    }
}

我当前项目中的代码

为什么需要测试异常?
在我当前的项目中,我有接收

double
作为参数的方法。如果该值为
<= 0
,则抛出异常。由于我刚开始进行单元测试,我认为这种情况也必须进行测试。

    public static double CalculateEmployerStatutoryPensionContribution(double grossSalary)
    {
        if (grossSalary <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(grossSalary), "The argument must have a positive value!");
        }

        return grossSalary * RentenversichungArbeitgeberPflichtanteil;
    }
c# nunit
2个回答
1
投票

考虑到您的最后一个例子,我尝试回答您问题的最后部分。首先,您必须测试您的逻辑而不是 .NET

ArgumentOutOfRangeException
。 为此,您应该创建三个不同的场景来测试可以找到
grossSalary
值的所有情况,如下所示:

    public class PensionContributionTests
    {
        [Test]
        public void CalculateEmployerStatutoryPensionContribution_NegativeValue_ThrowsException()
        {
            // Arrange
            double negativeGrossSalary = -1000.0; // Adjust the value as needed

            // Act & Assert
            Assert.Throws<ArgumentOutOfRangeException>(() =>
            {
                CalculateEmployerStatutoryPensionContribution(negativeGrossSalary);
            }, "The argument must have a positive value!");
        }

        [Test]
        public void CalculateEmployerStatutoryPensionContribution_ZeroValue_ThrowsException()
        {
            // Arrange
            double zeroGrossSalary = 0.0; // Adjust the value as needed

            // Act & Assert
            Assert.Throws<ArgumentOutOfRangeException>(() =>
            {
                CalculateEmployerStatutoryPensionContribution(zeroGrossSalary);
            }, "The argument must have a positive value!");
        }

        [Test]
        public void CalculateEmployerStatutoryPensionContribution_PositiveValue_DoesNotThrowException()
        {
            // Arrange
            double positiveGrossSalary = 5000.0; // Adjust the value as needed

            // Act & Assert
            Assert.DoesNotThrow(() =>
            {
                var result = CalculateEmployerStatutoryPensionContribution(positiveGrossSalary);
                // You can also add assertions to check the result if needed
            });
        }
    }

0
投票

谢谢您的回复!

我的学习

我需要使用这些 lamda 表达式进行大量训练。

解决方案

我的一次尝试确实是这样的。由于语法使用不正确,它不起作用。

Assert.Throws<ArgumentOutOfRangeException>(() => 
    BusinessMiniJob.CalculateEmployeeSalary(valueMayNotBeZero), 
    "The argument must have a positive value!");

Luca 的代码确实看起来像这样(根据我当前的测试进行了修改)。这段代码工作正常。对我来说,这是一个比我想象的更好、更易读的解决方案(参见线程顶部)。

        Assert.Throws<ArgumentOutOfRangeException>(() =>
        {
            BusinessMiniJob.CalculateEmployeeSalary(grossSalary);
        }, "The argument must have a positive value!");

更新了项目代码

这里我正在测试例外情况。

    private static IEnumerable<double> SourceProviderException()
    {
        // GrossSalary
        yield return 0.0;
        yield return -10.0;
    }

    [TestCaseSource(nameof(SourceProviderException))]
    public void EmployerStatutoryPensionContributionTest_ThrowsException(double grossSalary)
    {
        // ***** Arrange *****

        // ***** Act & Assert *****
        Assert.Throws<ArgumentOutOfRangeException>(() =>
        {
            BusinessMiniJob.CalculateEmployerStatutoryPensionContribution(grossSalary);
        }, "The argument must have a positive value!");
    }

这里我正在测试该方法的计算。提供

grossSalary
并列出预期结果。 (在这种情况下,有一些参数我没有使用;还有更多方法使用相同的
SourceProvider
)。

    private static IEnumerable<double[]> SourceProvider()
    {
        // GrossSalary, Salary, EmployeeStatutoryPensionContribution, EmployerStatutoryPensionContribution
        yield return new[] { 175.00, 168.70, 6.30, 26.25 };
        yield return new[] { 150.00, 139.95, 10.05, 22.50 };
        yield return new[] { 25.00, -3.80, 28.80, 3.75 };
    }

    [TestCaseSource(nameof(SourceProvider))]
    public void EmployerStatutoryPensionContributionTest(double grossSalary, double salary, double employeeContribution, double employerContribution)
    {
        // ***** Arrange *****

        // ***** Act *****
        var result = BusinessMiniJob.CalculateEmployerStatutoryPensionContribution(grossSalary);

        // ***** Assert *****
        Assert.That(result.ToString("c2"), Is.EqualTo(employerContribution.ToString("c2")));
    }
© www.soinside.com 2019 - 2024. All rights reserved.