Coder Perfect

How do I assert the type of the exception using Assert.Throws?

Problem

What is the best way to use Assert? To assert the type of exception and the actual message language, use throws.

Something like this:

Assert.Throws<Exception>(
    ()=>user.MakeUserActive()).WithMessage("Actual exception message")

I need a means to test that the correct message is thrown depending on the context because the method I’m testing throws numerous messages of the same type with various messages.

Asked by epitka

Solution #1

Assert. Throws returns the exception that was thrown, allowing you to assert on it.

var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));

The initial Assert.Throws assertion will fail if no exception is thrown or if an exception of the wrong kind is thrown. You can now assert on the actual exception that you’ve saved in the variable if an exception of the correct kind is thrown.

You can assert on anything other than the exception message using this pattern, for example, in the case of ArgumentException and derivatives, you can assert that the argument name is correct:

var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));

These asserts can also be done with the fluent API:

Assert.That(() => foo.Bar(null), 
Throws.Exception
  .TypeOf<ArgumentNullException>()
  .With.Property("ParamName")
  .EqualTo("bar"));

or alternatively

Assert.That(
    Assert.Throws<ArgumentNullException>(() =>
        foo.Bar(null)
    .ParamName,
Is.EqualTo("bar"));

ing on exception messages is to add the SetCultureAttribute to the test function to ensure that the thrown message uses the expected culture. This is relevant if you want to localize your exception messages by storing them as resources.

Answered by Patrik Hägne

Solution #2

The ExpectedException characteristics, for example, can now be used.

[Test]
[ExpectedException(typeof(InvalidOperationException), 
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}

Answered by Jackson Pope

Solution #3

Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));

Answered by Jordan Morris

Solution #4

A solution that actually works is as follows:

public void Test() {
    throw new MyCustomException("You can't do that!");
}

[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
    var exception = Assert.ThrowsException<MyCustomException>(
        () => Test(),
        "This should have thrown!");
    Assert.AreEqual("You can't do that!", exception.Message);
}

This is possible when using Microsoft. VisualStudio. TestTools. UnitTesting;.

Answered by Tvde1

Solution #5

You can do the following to expand on persistent’s response and add extra NUnit functionality:

public bool AssertThrows<TException>(
    Action action,
    Func<TException, bool> exceptionCondition = null)
    where TException : Exception
{
    try
    {
        action();
    }
    catch (TException ex)
    {
        if (exceptionCondition != null)
        {
            return exceptionCondition(ex);
        }
        return true;
    }
    catch
    {
        return false;
    }

    return false;
}

Examples:

// No exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => {}));

// Wrong exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new ApplicationException(); }));

// Correct exception thrown - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException(); }));

// Correct exception thrown, but wrong message - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("ABCD"); },
        ex => ex.Message == "1234"));

// Correct exception thrown, with correct message - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("1234"); },
        ex => ex.Message == "1234"));

Answered by fre0n

Post is based on https://stackoverflow.com/questions/1609536/how-do-i-use-assert-throws-to-assert-the-type-of-the-exception