views:

33

answers:

3

If I want to test that a method throws an exception of a particular type, NUnit's ExpectedException attribute doesn't care about the actual type; if I throw a generic Exception before the method call, the test passes:

    [Test, ExpectedException(typeof(TestCustomException))]
    public void FirstOnEmptyEnumerable()
    {
        throw new Exception(); // with this, the test should fail, but it doesn't
        this.emptyEnumerable.First(new TestCustomException());
    }

If I want to check that the test throws the exact exception type, I have to do something manual like this:

    [Test]
    public void FirstOnEmptyEnumerable()
    {
        try
        {
            throw new Exception();  // now the test fails correctly.
            this.emptyEnumerable.First(new TestCustomException());
        }
        catch (TestCustomException)
        {
            return;
        }

        Assert.Fail("Exception not thrown.");
    }

Am I missing something?

A: 

I always test for the string representation of the exception e.g.:

[Test, ExpectedException("Your.Namespace.TestCustomException")]
public void FirstOnEmptyEnumerable()
{
    throw new Exception(); // with this, the test should fail, but it doesn't
    this.emptyEnumerable.First(new TestCustomException());
}

Which seems to work fine for me.

Jackson Pope
In general it is not recommended to use strings like this. If you change the name of your exception the test would be invalid. Fortunately in this case the test would start failing though, so you would probably see this and update the ExceptedException in the test. Still, it's a pain to have to go through this.. Advantage using the string is that you don't need to reference the assembly holding the exception definition.
stiank81
Thanks for the info. If the strings way is not recommended and the `typeof()` way is not working for the OP what way do you recommend?
Jackson Pope
I posted an answer to how I would do it.. Please continue using string definitions if you're comfortable with it, but just be aware it might bite you some day.
stiank81
+2  A: 

I've never used ExpectedException, so I don't have any experience to share on this. An option is to Assert that it Throws directly inside the test. Something like this:

[Test]
public void FirstOnEmptyEnumerable()
{
    Assert.Throws<TestCustomException>(() => this.emptyEnumerable.First(new TestCustomException()));
}

I find this approach more readable as you test for the exception exactly where you expect it to happen instead of saying "somewhere inside this function I except an exception to be thrown".

stiank81
+1 Much nicer solution :)
Jackson Pope
It's a nice idea and I think it'll fit most cases, but I try to avoid catching exceptions in asserts as a test. I like the distinction between the two (exception and result) and moreover I feel it complicated my tests (two types of tests)
Neowizard
I guess it's a matter of preferences. I prefer this approach. Thanks Jackson Pope!
stiank81
@Neowizard: emptyEnumerable.First is a Linq-style helper extension method that throws a custom exception if the sequence is empty, so, in this case, testing that it throws the correct exception makes sense. ;)
Notoriousxl
@stiank81: Nice idea, NUnit should add it :)
Notoriousxl
A: 

If you want to use the ExpectedException(string) signature, the best practice would be to use typeof(Exception).Name and typeof(Exception).Namespace

Neowizard