Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing for exceptions with [TestCase] attribute in NUnit 3?

How do I test for exceptions in a TestCase with NUnit3?

Let's say I have a method Divide(a,b) defined as follows:

public double Divide(double a, double b)
{
    if(Math.Abs(b) < double.Epsilon) throw new ArgumentException("Divider cannot be 0");
    return a/b;
}

I want to test this method using NUnit 3.0 test cases, so maybe I have:

[TestCase(-10, 2, -5)]
[TestCase(-1, 2, -0.5)]
public void TestDivide(double a, double b, double result)
{
    Assert.That(_uut.Divide(a, b), Is.EqualTo(result));
}

Is there a way to specify a Test Case that will cause Divide() to throw an ArgumentException and somehow have this as the expected result, e.g. something along the lines of:

[TestCase(-10, 2, -5)]
[TestCase(-1, 2, -0.5)]
[TestCase(-1, 0, ExpectedResult = TypeOf(ArgumentException)]
public void TestDivide(double a, double b, double result)
{
    Assert.That(_uut.Divide(a, b), Is.EqualTo(result));
}

(Of course I could define a separate test method and use Assert.Throws() in this, so this is purely out of curiosity)

like image 597
Corpus Gigantus Avatar asked Jan 28 '16 12:01

Corpus Gigantus


People also ask

How do I use the TestCase attribute in NUnit?

The TestCase attribute in NUnit marks a method with parameters as a test method. It also provides the inline data that needs to be used when that particular method is invoked. It can appear one or more times on the test method, with each appearance carrying values for the test case.

How do you write a TestCase in NUnit?

There are other NUnit attributes that enable you to write a suite of similar tests. A [TestCase] attribute is used to create a suite of tests that execute the same code but have different input arguments. You can use the [TestCase] attribute to specify values for those inputs.


Video Answer


2 Answers

ExpectedException would have been the correct method for NUnit 2.X, but it was removed from NUnit 3.

There's a various snippets of discussion in the NUnit Google Group and the equivalent Dev group - but it looks like the decision was made that it's generally a better design pattern to test expected outcomes, and exceptions in separate methods. (link)

The only way to do this in NUnit 3, would be to break it down in to two separate tests. (Confirmed in a similar question answered by the NUnit core team, here.)

[TestCase(-10, 2, -5)]
[TestCase(-1, 2, -0.5)]
public void TestDivide(double a, double b, double result)
{
    Assert.That(_uut.Divide(a, b), Is.EqualTo(result));
}

[TestCase(-1, 0)]
public void TestDivideThrows(double a, double b)
{
    Assert.That(() => _uut.Divide(a, b), Throws.TypeOf<ArgumentException>());
}
like image 101
Chris Avatar answered Sep 27 '22 01:09

Chris


I agree with the Corpus Gigantus's answer but why don't you simplify thing like this:

[TestCase(-10, 2, -5)]
[TestCase(-1, 2, -0.5)]
[TestCase(-1, 0, null, typeof(ArgumentException))]
public void TestDivide(double a, double b, double result, Type exception = null)
{
    if(exception != null)
    {
        Assert.Throws(exception, delegate { _uut.Divide(a, b);  });
                
    } else Assert.That(_uut.Divide(a, b), Is.EqualTo(result));
}

In this way, the expected exception is part of the test parameters as well, note that you can only have two outcome, either the division succeeds or throws.

like image 7
Oliamster Avatar answered Sep 25 '22 01:09

Oliamster