## Why is this an issue?

It should be clear to a casual reader what code a test is testing and what results are expected. Unfortunately, that’s not usually the case with the `ExpectedException` attribute since an exception could be thrown from almost any line in the method.

This rule detects MSTest and NUnit `ExpectedException` attribute.

### Exceptions

This rule ignores:

- single-line tests, since it is obvious in such methods where the exception is expected to be thrown
- tests when it tests control flow and assertion are present in either a `catch` or `finally` clause

    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void UsingTest()
    {
        Console.ForegroundColor = ConsoleColor.Black;
        try
        {
            using var _ = new ConsoleAlert();
            Assert.AreEqual(ConsoleColor.Red, Console.ForegroundColor);
            throw new InvalidOperationException();
        }
        finally
        {
            Assert.AreEqual(ConsoleColor.Black, Console.ForegroundColor); // The exception itself is not relevant for the test.
        }
    }

    public sealed class ConsoleAlert : IDisposable
    {
        private readonly ConsoleColor previous;

        public  ConsoleAlert()
        {
            previous = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
        }

        public void Dispose() =>
            Console.ForegroundColor = previous;
    }

## How to fix it in MSTest

Remove the `ExpectedException` attribute in favor of using the Assert.ThrowsException assertion.

### Code examples

#### Noncompliant code example

    [TestMethod]
    [ExpectedException(typeof(ArgumentNullException))]  // Noncompliant
    public void Method_NullParam()
    {
        var sut = new MyService();
        sut.Method(null);
    }

#### Compliant solution

    [TestMethod]
    public void Method_NullParam()
    {
        var sut = new MyService();
        Assert.ThrowsException<ArgumentNullException>(() => sut.Method(null));
    }

## How to fix it in NUnit

Remove the `ExpectedException` attribute in favor of using the Assert.Throws assertion.

### Code examples

#### Noncompliant code example

    [Test]
    [ExpectedException(typeof(ArgumentNullException))]  // Noncompliant
    public void Method_NullParam()
    {
        var sut = new MyService();
        sut.Method(null);
    }

#### Compliant solution

    [Test]
    public void Method_NullParam()
    {
        var sut = new MyService();
        Assert.Throws<ArgumentNullException>(() => sut.Method(null));
    }

## Resources

### Documentation

- Microsoft Learn - Assert.ThrowsException Method
- Microsoft Learn - ExpectedExceptionAttribute Class
- NUnit - Assert.Throws
- NUnit - ExpectedExceptionAttribute