Let's say, we have a method doStuff in the class FooService. This method can throw a NullPointerException when a null flag is passed in the argument.
public class FooService {
  public void doStuff(Boolean flag) {
    try{
      if(flag){
        // do stuff
      }
    }catch (Exception e){
      throw new RuntimeException("Unexpected error occurred", e);
    }
  }
}
Using Junit 5
Junit 5 assertThrows returns exception, which can be used to assert exception message as per below example:-
import static org.junit.jupiter.api.Assertions.*;
@Test
public void doStuff_testThrownException(){   
    // null is passed, expected NullPointerException
    Throwable exception = assertThrows(RuntimeException.class, () -> fooService.doStuff(null)); 
    assertEquals("Unexpected error occurred", exception.getMessage());
}
Using AssertJ
AssertJ has various assertions to test exception, one of them is assertThatRuntimeException which can be chained with withMessage to test exception message
import static org.assertj.core.api.Assertions.*;
@Test
public void doStuff_testThrownException(){
  // null is passed, expected NullPointerException
  assertThatRuntimeException().isThrownBy(() -> fooService.doStuff(null))
          .withMessage("Unexpected error occurred");
}
Source: CodingNConcepts