Testing Exceptions in Nunit 3.0 and above

Viewed 2546

I am trying to test an exception, NUnit 3.11 is giving me the error, and the unit test is failing. I want Nunit to green pass if it receives this exception, not error out. How would I resolve this?

Feel free to improve code if you want, just started learning programming few months ago.

When running it gives the exception itself, does not pass.

Test errors out- Message: System.ArgumentException : Too much data

public class ParseVendorSupply
{
    public VendorSupply FromCsv(string csvLine)
    {
        string[] values = csvLine.Split(',');
        if (values.Length > 3)
        {
            throw new System.ArgumentException("Too much data");
        }
        VendorSupply vendorsupply = new VendorSupply();
        vendorsupply.VendorId = Convert.ToInt16(values[0]);
        vendorsupply.ProductId = Convert.ToInt16(values[1]);
        vendorsupply.Quantity = Convert.ToInt16(values[2]);
        return vendorsupply;
    }
}

Test:

public class ParseVendorSupplyNunit
{

    ParseVendorSupply parseVendorSupplytest = new ParseVendorSupply();

    [Test]
    public void FromCsv_ParseCorrectly_Extradata()
    {
        string csvLineTest = "5,8,3,9,5";
        //VendorSupply vendorsupply = parseVendorSupplytest.FromCsv(csvLineTest);
        Assert.That(parseVendorSupplytest.FromCsv(csvLineTest), Throws.ArgumentException);
    }
3 Answers

You need to pass the method you are testing as an Action. You can then use the Assert.Throws<> method:

Assert.Throws<ArgumentException>(() => parseVendorSupplytest.FromCsv(csvLineTest));

There is also an async version if you are using async/await

Assert.ThrowsAsync<ArgumentException>(async () => await parseVendorSupplytest.FromCsv(csvLineTest));

The answers that suggest using an Action work, but the Action is not necessary for NUnit. I'm creating this one because I think it's important that you understand why your existing code doesn't work.

Problem is that the first argument of your assert calls the method before calling the assert. Your Assert.That never gets called since the exception is thrown while evaluating the argument.

Defining an Action avoids this problem because it specifies a method call that won't be made immediately.

However, a more colloquial way to specify this in NUnit is by using a lambda directly...

Assert.That(() => parseVendorSupplytest.FromCsv(csvLineTest), Throws.ArgumentException);

Wrap method you are testing into an Action

Action parseFromCsv = () => parseVendorSupplytest.FromCsv(csvLineTest);
Assert.That(parseFromCsv, Throws.ArgumentException)

And when testing for common exceptions, such as ArgumentException, always test for exception message as well.
Because common exception can occur in some other places and test will pass for a wrong reason.

I prefer to use FluentAssertions, which I found little bid more readable.

Action parseFromCsv = () => parseVendorSupplytest.FromCsv(csvLineTest);
parseFromCsv.Should().Throw<ArgumentException>().WithMessage("Too much data");
Related