## 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(GetType(InvalidOperationException))>
    Public Sub UsingTest()
        Console.ForegroundColor = ConsoleColor.Black
        Try
            Using alert As New ConsoleAlert()
                Assert.AreEqual(ConsoleColor.Red, Console.ForegroundColor)
                Throw New InvalidOperationException()
            End Using
        Finally
            Assert.AreEqual(ConsoleColor.Black, Console.ForegroundColor) ' The exception itself is not relevant for the test.
        End Try
    End Sub

    Public NotInheritable Class ConsoleAlert
        Implements IDisposable

        Private ReadOnly previous As ConsoleColor

        Public Sub New()
            previous = Console.ForegroundColor
            Console.ForegroundColor = ConsoleColor.Red
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            Console.ForegroundColor = previous
        End Sub
    End Class

## 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(GetType(ArgumentNullException))>  ' Noncompliant
    Public Sub Method_NullParam()
        Dim sut As New MyService()
        sut.Method(Nothing)
    End Sub

#### Compliant solution

    <TestMethod>
    Public Sub Method_NullParam()
        Dim sut As New MyService()
        Assert.ThrowsException(Of ArgumentNullException)(Sub() sut.Method(Nothing))
    End Sub

## 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(GetType(ArgumentNullException))>  ' Noncompliant
    Public Sub Method_NullParam()
        Dim sut As New MyService()
        sut.Method(Nothing)
    End Sub

#### Compliant solution

    <Test>
    Public Sub Method_NullParam()
        Dim sut As New MyService()
        Assert.Throws(Of ArgumentNullException)(Sub() sut.Method(Nothing))
    End Sub

## Resources

### Documentation

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