Assert.Throws
The Assert.Throws method is pretty much in a class by itself. Rather than comparing values, it attempts to invoke a code snippet, represented as a delegate, in order to verify that it throws a particular exception.
It's also in a class by itself in that it returns an Exception, rather than void, if the Assert is successful. See the example below for a few ways to use this.
Assert.Throws may be used with a constraint argument, which is applied to the actual exception thrown, or with the Type of exception expected. The Type format is available in both a non-generic and generic form.
If the code under test is async, you must use Assert.ThrowsAsync.
Exception Assert.Throws(Type expectedExceptionType, TestDelegate code);
Exception Assert.Throws(Type expectedExceptionType, TestDelegate code,
string message, params object[] params);
Exception Assert.Throws(IResolveConstraint constraint, TestDelegate code);
Exception Assert.Throws(IResolveConstraint constraint, TestDelegate code,
string message, params object[] params);
Assert.Throws<T>(TestDelegate code);
Assert.Throws<T>(TestDelegate code,
string message, params object[] params);
In the above code TestDelegate is a delegate of the form void TestDelegate(), which is used to execute the code in question. This may be an anonymous delegate or, when compiling under C# 3.0 or greater, a lambda expression.
The following example shows different ways of writing the same test.
[TestFixture]
public class AssertThrowsTests
{
[Test]
public void Tests()
{
// Using a method as a delegate
Assert.Throws<ArgumentException>(MethodThatThrows);
// Using an anonymous delegate
Assert.Throws<ArgumentException>(
delegate { throw new ArgumentException(); });
// Using a Lambda expression
Assert.Throws<ArgumentException>(
() => throw new ArgumentException());
}
void MethodThatThrows()
{
throw new ArgumentException();
}
}
If, for example, we were to assume a custom exception class of:
public class MyException : Exception
{
public int MyParam { get; }
public MyException(string message, int myParam) : base(message)
{
MyParam = myParam;
}
}
The below example shows use of the return value to perform additional verification of the exception.
[TestFixture]
public class UsingReturnValue
{
[Test]
public void TestException()
{
MyException ex = Assert.Throws<MyException>(
() => throw new MyException("message", 42));
Assert.That(ex.Message, Is.EqualTo("message"));
Assert.That(ex.MyParam, Is.EqualTo(42));
}
}
This example does the same thing using the overload that includes a constraint.
[TestFixture]
public class UsingConstraint
{
[Test]
public void TestException()
{
Assert.Throws(Is.TypeOf<MyException>()
.And.Message.EqualTo("message")
.And.Property("MyParam").EqualTo(42),
() => throw new MyException("message", 42));
}
}
Use the form that matches your style of coding.
Exact Versus Derived Types
When used with a Type argument, Assert.Throws requires that exact type to be thrown. If you want to test for any derived Type, use one of the forms that allows specifying a constraint. Alternatively, you may use Assert.Catch, which differs from Assert.Throws in allowing derived types. See the following code for examples:
// Require an ApplicationException - derived types fail!
Assert.Throws(typeof(ApplicationException), code);
Assert.Throws<ApplicationException>(code);
// Allow both ApplicationException and any derived type
Assert.Throws(Is.InstanceOf(typeof(ApplicationException)), code);
Assert.Throws(Is.InstanceOf<ApplicationException>(), code);
// Allow both ApplicationException and any derived type
Assert.Catch<ApplicationException>(code);
// Allow any kind of exception
Assert.Catch(code);