Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static Throwable getActualCause(MethodInvocationException exception) {
/**
* 获取异常的原因。
*
* @param throwable 表示指定异常的 {@link Exception}。
* @param throwable 表示指定异常的 {@link Throwable}。
* @return 表示异常原因的 {@link String}。
*/
public static String getReason(Throwable throwable) {
Expand All @@ -64,4 +64,23 @@ public static String getReason(Throwable throwable) {
}
return throwable.getClass().getSimpleName() + ": " + throwable.getMessage();
}

/**
* 获取从异常链中找出第一个非空的异常消息。
*
* @param throwable 表示指定异常的 {@link Throwable}。
* @return 表示异常原因的 {@link String}。
*/
public static String getActualMessage(Throwable throwable) {
Set<Throwable> visited = new HashSet<>();
while (throwable != null && !visited.contains(throwable)) {
visited.add(throwable);
String message = throwable.getMessage();
if (StringUtils.isNotBlank(message)) {
return message;
}
throwable = throwable.getCause();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,43 @@ void givenExceptionCauseHasAnotherTypeCauseThenGetItsDescendantsCause() {
assertThat(actualCause).isNotNull().hasMessage("error");
}
}

@Nested
@DisplayName("test getActualMessage(Throwable throwable)")
class WhenGetActualMessage {
@Test
@DisplayName("when throwable has non-blank message, return the message")
void givenThrowableWithMessageThenReturnMessage() {
Throwable throwable = new Exception("Error occurred");
String message = ExceptionUtils.getActualMessage(throwable);
assertThat(message).isEqualTo("Error occurred");
}

@Test
@DisplayName("when throwable chain has non-blank message in deep cause, return the first valid message")
void givenDeepThrowableChainThenReturnFirstValidMessage() {
Throwable cause = new Exception("Root cause");
Throwable throwable = new Exception(null, new Exception(" ", cause));
String message = ExceptionUtils.getActualMessage(throwable);
assertThat(message).isEqualTo("Root cause");
}

@Test
@DisplayName("when throwable chain has all blank messages, return null")
void givenAllBlankMessagesThenReturnNull() {
Throwable throwable = new Exception(null, new Exception(" "));
String message = ExceptionUtils.getActualMessage(throwable);
assertThat(message).isNull();
}

@Test
@DisplayName("when throwable chain has circular reference, return valid message")
void givenCircularReferenceThenReturnFirstValidMessage() {
Exception e1 = new Exception("e1");
Exception e2 = new Exception("e2", e1);
e1.initCause(e2);
assertThat(ExceptionUtils.getActualMessage(e1)).isEqualTo("e1");
assertThat(ExceptionUtils.getActualMessage(e2)).isEqualTo("e2");
}
}
}