holyredbeard
holyredbeard

Reputation: 21208

Checking if argument is thrown in unit-tests

I'm working on unit-tests for an application which has a constructor that takes three values as arguments. The numbers shall be 0 or higher, and now I'm writing on an unit-test for the constructor that throws an exception if this is not the case.

What I can't figure out is how I what to write after "Assert" to determine this so that the test passes if illegal numbers are passed to the constructor. Thanks in advance.

EDIT: I'm using MSTest framework

   public void uniqueSidesTest2()
    {
        try {
            Triangle_Accessor target = new Triangle_Accessor(0, 10, 10);
        }
        catch (){
            Assert // true (pass the test)
            return;
        }

        Assert. // false (test fails)
    }

// From the code...

    public Triangle(double a, double b, double c) {
        if ((a <= 0) || (b <= 0) || (c <= 0)){
            throw new ArgumentException("The numbers must higher than 0.");
        }
        sides = new double[] { a, b, c };
    }

Upvotes: 5

Views: 7941

Answers (6)

Toni Parviainen
Toni Parviainen

Reputation: 2387

If you don't have nunit (or other framework that has this support built in you can use the following type of helper method

 public static void ThrowsExceptionOfType<T>(Action action) where T: Exception
    {
        try
        {
            action();
        }
        catch (T)
        {
            return;
        }
        catch (Exception exp)
        {
            throw new Exception(string.Format("Assert failed. Expecting exception of type {0} but got {1}.", typeof(T).Name, exp.GetType().Name));
        }

        throw new Exception(string.Format("Assert failed. Expecting exception of type {0} but no exception was thrown.", typeof(T).Name));
    }

Your test would look like this

AssertHelper.ThrowsExceptionOfType<ArgumentException>( 
    () => 
    {
        new Triangle_Accessor(0, 10, 10);
    });

Upvotes: 2

jamesmillerio
jamesmillerio

Reputation: 3204

It may not be the best solution, but if I'm testing to make sure an Exception is thrown, I will do something like the following:

public void uniqueSidesTest2()
{
    try {
        Triangle_Accessor target = new Triangle_Accessor(0, 10, 10);
        Assert.Fail("An exception was not thrown for an invalid argument.");
    }
    catch (ArgumentException ex){
        //Do nothing, test passes if Assert.Fail() was not called
    }
}

Since your constructor call should throw an error, if it ever gets to the second line (The Assert.Fail() line) then you know it didn't properly throw the exception.

Upvotes: 2

Roy Dictus
Roy Dictus

Reputation: 33139

First of all, you should throw an ArgumentOutOfRangeException rather than just an ArgumentException.

Second, your unit test should expect an Exception to be thrown, like so:

[ExpectedException(typeof(ArgumentOutOfRangeException))]
public static void MyUnitTestForArgumentA()
{
    ...
}

So, you need to create separate unit tests -- one for each argument -- that test whether the method throws a correct exception when the argument is out of range.

Upvotes: 10

tnktnk
tnktnk

Reputation: 512

You don't mention what framework you are using for unit testing, but I think what you're looking for is something like what is shown here:

http://www.nunit.org/index.php?p=exception&r=2.4

Upvotes: 0

Myles McDonnell
Myles McDonnell

Reputation: 13335

No need to use a try catch block. Using NUnit or the MSTest framework you can use an attribute on your test method declaration to specify that you expect an exception.

MSTest

 [TestMethod]
 [ExpectedException(typeof(ArgumentException))]
 public void uniqueSidesTest2()

Upvotes: 4

Hans Kesting
Hans Kesting

Reputation: 39284

You will not need an Assert in the catch (but you might want to catch a more specific exception, like ArgumentException).

To always fail, there is an Assert.Fail.

Upvotes: 0

Related Questions