Search code examples
c#nunitdata-driven-tests

Why does NUnit tell me "Not enough arguments provided, provide at least 2 arguments." when I'm providing 2 arguments?


Given I have the following TestFixture with TestCase arguments as pairs of decimal, int (because C# doesn't support decimal directly in an attribute).

[TestFixture]
public static class GetNumberOfSignificantDecimalPlacesTests
{
    public static IEnumerable<object[]> DecimalTestData { get; } = new[]
    {
        new object[]
        {
            new[]
            {
                0m,
                0
            }
        },
        new object[]
        {
            new[]
            {
                0.1m,
                1
            }
        },
        new object[]
        {
            new[]
            {
                -0.1m,
                1
            }
        }
    };

    [TestCaseSource(nameof(DecimalTestData))]
    public static void ShouldIdentifyTheCorrectNumberOfDecimalPlaces(decimal @decimal, int expected)
        => Assert.AreEqual
        (
            expected,
            Math.DigitExtensions.GetNumberOfSignificantDecimalPlaces(@decimal)
        );

Why do I get the following exception from N-Unit when I try to run these tests?

Not enough arguments provided, provide at least 2 arguments.

I have written more complex data-driven unit tests in the same manner whereby each parameter is an IEnumerable of a custom struct I made and have no problems getting those to run, so why does N-Unit have a problem with what should be a much simpler unit test?


Solution

  • You are not passing two arguments to the method, but only one. For example, the first call passes an object[] containing two values, 0m and 0.

    I find that it's very easy to get confused when using object arrays to pass the information and, of course, it's not type safe. And even if it doesn't confuse you, it's likely to confuse those who read your code.

    I'd tend to do something like this instead...

    public static IEnumerable<TestCaseData> DecimalTestData { get; } = new[]
    {
        new TestCaseData(0m, 0),
        ...
    }
    

    I find it more readable and it also gives you the opportunity to do things like assigning test names, ignoring some tests, etc.