Throws Constraint
ThrowsConstraint is used to test that code, represented as a delegate, throws a particular exception. It may be used
alone to test the exception type, or with additional constraints applied to the exception itself. The related
ThrowsNothingConstraint asserts that the delegate does not throw.
Usage
Throws.Exception
Throws.TypeOf<T>()
Throws.TypeOf(Type expectedType)
Throws.InstanceOf<T>()
Throws.InstanceOf(Type expectedType)
// Common exception shortcuts
Throws.ArgumentException
Throws.ArgumentNullException
Throws.InvalidOperationException
Throws.TargetInvocationException
// For testing nothing is thrown
Throws.Nothing
Modifiers
.With.Message.EqualTo(string) // Test exception message
.With.Message.Contains(string) // Test message contains substring
.With.Property("Name").EqualTo(x) // Test exception property
.With.InnerException.TypeOf<T>() // Test inner exception
.ParamName.EqualTo(string) // Test ArgumentException.ParamName
ParamName
Note
This property was added in NUnit 5.0.
For ArgumentException and derived types, the generic exception constraints have a ParamName property. It checks
which parameter caused the exception, without needing .With.Property("ParamName"). It is available after
Throws.TypeOf<T>(), Throws.InstanceOf<T>(), Throws.ArgumentException and Throws.ArgumentNullException, and
must come directly after them in the constraint expression.
ParamName is a C# 14 extension property, so your test project must use C# 14 or later.
[Test]
public void ThrowsConstraint_ParamName_Examples()
{
// ParamName is available on constraints for ArgumentException and derived types
Assert.That(() => Greet(null!), Throws.ArgumentNullException.ParamName.EqualTo("name"));
Assert.That(() => Greet(""), Throws.TypeOf<ArgumentException>().ParamName.EqualTo("name"));
// InstanceOf also accepts derived types, such as ArgumentNullException
Assert.That(() => Greet(null!), Throws.InstanceOf<ArgumentException>().ParamName.EqualTo("name"));
}
private static string Greet(string name)
{
ArgumentNullException.ThrowIfNull(name);
if (name.Length == 0)
throw new ArgumentException("Name cannot be empty.", nameof(name));
return $"Hello, {name}";
}
Examples
[Test]
public void ThrowsConstraint_Basic_Examples()
{
// Test for specific exception type
Assert.That(() => ThrowArgumentException(), Throws.TypeOf<ArgumentException>());
Assert.That(() => ThrowArgumentException(), Throws.InstanceOf<Exception>());
// Test exception message
Assert.That(() => throw new ArgumentException("bad value"),
Throws.ArgumentException.With.Message.EqualTo("bad value"));
// Test with lambda expression
Assert.That(() => int.Parse("abc"), Throws.TypeOf<FormatException>());
// Assert no exception is thrown
Assert.That(() => SafeMethod(), Throws.Nothing);
}
private static void ThrowArgumentException() => throw new ArgumentException("test");
private static void SafeMethod() { }
Additional Examples
[Test]
public void ThrowsConstraint_Examples()
{
Assert.That(() => throw new ArgumentException(), Throws.ArgumentException);
Assert.That(() => throw new InvalidOperationException("test"),
Throws.InvalidOperationException.With.Message.EqualTo("test"));
Assert.That(() => { }, Throws.Nothing);
}
Notes
- Throws.TypeOf requires an exact type match. Use Throws.InstanceOf to allow derived exception types.
- Throws.Exception can be followed by additional constraints on the exception object. Avoid using it alone without type checking, as you should generally know what exception to expect.
- For async code, use
Assert.ThrowsAsyncor test the async delegate directly withThrows. - Throws.InnerException tests the InnerException property. Combine it with outer exception type tests for full validation.