Skip to content

Commit

Permalink
Added Throwable Stacktrace to ShouldHaveRootCauseInstance and ShouldH…
Browse files Browse the repository at this point in the history
…aveRootCauseExactlyInstance

Fix error messages that were displaying actual instance actual type
Fix #2910
  • Loading branch information
Ds2994 authored and joel-costigliola committed Jan 24, 2023
1 parent 85e5b1e commit 9739d69
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*/
package org.assertj.core.error;

import static org.assertj.core.util.Strings.escapePercent;
import static org.assertj.core.util.Throwables.getStackTrace;

import org.assertj.core.util.Throwables;

/**
Expand All @@ -30,20 +33,20 @@ public class ShouldHaveRootCauseExactlyInstance extends BasicErrorMessageFactory
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldHaveRootCauseExactlyInstance(Throwable actual,
Class<? extends Throwable> expectedCauseType) {
return Throwables.getRootCause(actual) == null ? new ShouldHaveRootCauseExactlyInstance(expectedCauseType)
Class<? extends Throwable> expectedCauseType) {
return Throwables.getRootCause(actual) == null
? new ShouldHaveRootCauseExactlyInstance(expectedCauseType, actual)
: new ShouldHaveRootCauseExactlyInstance(actual, expectedCauseType);
}

private ShouldHaveRootCauseExactlyInstance(Throwable actual, Class<? extends Throwable> expectedCauseType) {
super(
"%nExpecting a throwable with root cause being exactly an instance of:%n %s%nbut was an instance of:%n %s",
expectedCauseType, Throwables.getRootCause(actual));
super("%nExpecting a throwable with root cause being exactly an instance of:%n %s%nbut was an instance of:%n %s%n" +
"%nThrowable that failed the check:%n" + escapePercent(getStackTrace(actual)),
expectedCauseType, Throwables.getRootCause(actual).getClass());
}

private ShouldHaveRootCauseExactlyInstance(Class<? extends Throwable> expectedCauseType) {
super(
"%nExpecting a throwable with root cause being exactly an instance of:%n %s%nbut current throwable has no cause.",
expectedCauseType);
private ShouldHaveRootCauseExactlyInstance(Class<? extends Throwable> expectedCauseType, Throwable actual) {
super("%nExpecting a throwable with root cause being exactly an instance of:%n %s%nbut current throwable has no cause." +
"%nThrowable that failed the check:%n" + escapePercent(getStackTrace(actual)), expectedCauseType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*/
package org.assertj.core.error;

import static org.assertj.core.util.Strings.escapePercent;
import static org.assertj.core.util.Throwables.getStackTrace;

import org.assertj.core.util.Throwables;

/**
Expand All @@ -30,18 +33,20 @@ public class ShouldHaveRootCauseInstance extends BasicErrorMessageFactory {
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldHaveRootCauseInstance(Throwable actual,
Class<? extends Throwable> expectedCauseType) {
return Throwables.getRootCause(actual) == null ? new ShouldHaveRootCauseInstance(expectedCauseType)
Class<? extends Throwable> expectedCauseType) {
return Throwables.getRootCause(actual) == null
? new ShouldHaveRootCauseInstance(expectedCauseType, actual)
: new ShouldHaveRootCauseInstance(actual, expectedCauseType);
}

private ShouldHaveRootCauseInstance(Throwable actual, Class<? extends Throwable> expectedCauseType) {
super("%nExpecting a throwable with root cause being an instance of:%n %s%nbut was an instance of:%n %s",
expectedCauseType, Throwables.getRootCause(actual));
super("%nExpecting a throwable with root cause being an instance of:%n %s%nbut was an instance of:%n %s%n" +
"%nThrowable that failed the check:%n" + escapePercent(getStackTrace(actual)),
expectedCauseType, Throwables.getRootCause(actual).getClass());
}

private ShouldHaveRootCauseInstance(Class<? extends Throwable> expectedCauseType) {
super("%nExpecting a throwable with root cause being an instance of:%n %s%nbut current throwable has no cause.",
expectedCauseType);
private ShouldHaveRootCauseInstance(Class<? extends Throwable> expectedCauseType, Throwable actual) {
super("%nExpecting a throwable with root cause being an instance of:%n %s%nbut current throwable has no cause." +
"%nThrowable that failed the check:%n" + escapePercent(getStackTrace(actual)), expectedCauseType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,7 @@ public void assertHasRootCauseInstanceOf(AssertionInfo info, Throwable actual, C
* @throws AssertionError if the root cause of the actual {@code Throwable} is not <b>exactly</b> an instance of the
* given type.
*/
public void assertHasRootCauseExactlyInstanceOf(AssertionInfo info, Throwable actual,
Class<? extends Throwable> type) {
public void assertHasRootCauseExactlyInstanceOf(AssertionInfo info, Throwable actual, Class<? extends Throwable> type) {
assertNotNull(info, actual);
checkTypeIsNotNull(type);
Throwable rootCause = getRootCause(actual);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2023 the original author or authors.
*/
package org.assertj.core.error;

import static java.lang.String.format;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldHaveRootCauseExactlyInstance.shouldHaveRootCauseExactlyInstance;
import static org.assertj.core.util.Throwables.getStackTrace;

import java.io.IOException;

import org.assertj.core.internal.TestDescription;
import org.junit.jupiter.api.Test;

class ShouldHaveRootCauseExactlyInstance_create_Test {

private static final TestDescription DESCRIPTION = new TestDescription("TEST");

@Test
void should_create_error_message_when_actual_has_no_root_cause() {
// GIVEN
Throwable actual = new RuntimeException();
// WHEN
String message = shouldHaveRootCauseExactlyInstance(actual, IOException.class).create(DESCRIPTION);
// THEN
then(message).isEqualTo(format("[TEST] %n"
+ "Expecting a throwable with root cause being exactly an instance of:%n"
+ " java.io.IOException%n"
+ "but current throwable has no cause."
+ "%n"
+ "Throwable that failed the check:%n"
+ "%s",
getStackTrace(actual)));
}

@Test
void should_create_error_message_when_actual_has_a_root_cause() {
// GIVEN
Throwable rootCause = new IllegalStateException();
Throwable cause = new IllegalArgumentException(rootCause);
Throwable actual = new RuntimeException(cause);
// WHEN
String message = shouldHaveRootCauseExactlyInstance(actual, IOException.class).create(DESCRIPTION);
// THEN
then(message).isEqualTo(format("[TEST] %n"
+ "Expecting a throwable with root cause being exactly an instance of:%n"
+ " java.io.IOException%n"
+ "but was an instance of:%n"
+ " java.lang.IllegalStateException%n"
+ "%n"
+ "Throwable that failed the check:%n"
+ "%s",
getStackTrace(actual)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2023 the original author or authors.
*/
package org.assertj.core.error;

import static java.lang.String.format;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldHaveRootCauseInstance.shouldHaveRootCauseInstance;
import static org.assertj.core.util.Throwables.getStackTrace;

import java.io.IOException;

import org.assertj.core.internal.TestDescription;
import org.junit.jupiter.api.Test;

class ShouldHaveRootCauseInstance_create_Test {

private static final TestDescription DESCRIPTION = new TestDescription("TEST");

@Test
void should_create_error_message_when_actual_has_no_root_cause() {
// GIVEN
Throwable actual = new RuntimeException();
// WHEN
String message = shouldHaveRootCauseInstance(actual, IOException.class).create(DESCRIPTION);
// THEN
then(message).isEqualTo(format("[TEST] %n"
+ "Expecting a throwable with root cause being an instance of:%n"
+ " java.io.IOException%n"
+ "but current throwable has no cause."
+ "%n"
+ "Throwable that failed the check:%n"
+ "%s",
getStackTrace(actual)));
}

@Test
void should_create_error_message_when_actual_has_a_root_cause() {
// GIVEN
Throwable rootCause = new IllegalStateException();
Throwable cause = new IllegalArgumentException(rootCause);
Throwable actual = new RuntimeException(cause);
// WHEN
String message = shouldHaveRootCauseInstance(actual, IOException.class).create(DESCRIPTION);
// THEN
then(message).isEqualTo(format("[TEST] %n"
+ "Expecting a throwable with root cause being an instance of:%n"
+ " java.io.IOException%n"
+ "but was an instance of:%n"
+ " java.lang.IllegalStateException%n"
+ "%n"
+ "Throwable that failed the check:%n"
+ "%s",
getStackTrace(actual)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
package org.assertj.core.internal;


import static org.assertj.core.test.TestData.someInfo;
import static org.mockito.Mockito.spy;

import org.assertj.core.api.AssertionInfo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -30,6 +32,7 @@
*/
public class ThrowablesBaseTest {

protected static final AssertionInfo INFO = someInfo();
protected Failures failures;
protected Throwables throwables;
protected static Throwable actual;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@
*/
package org.assertj.core.internal.throwables;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldHaveRootCauseExactlyInstance.shouldHaveRootCauseExactlyInstance;
import static org.assertj.core.test.TestData.someInfo;
import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
import static org.assertj.core.util.FailureMessages.actualIsNull;
import static org.mockito.Mockito.verify;

import org.assertj.core.api.AssertionInfo;
import java.io.IOException;

import org.assertj.core.internal.ThrowablesBaseTest;
import org.junit.jupiter.api.Test;

Expand All @@ -34,57 +33,62 @@
*/
class Throwables_assertHasRootCauseExactlyInstanceOf_Test extends ThrowablesBaseTest {

private Throwable throwableWithCause = new Throwable(new Exception(new IllegalArgumentException()));
private static final Throwable throwableWithCause = new Throwable(new Exception(new IllegalArgumentException()));

@Test
void should_pass_if_root_cause_is_exactly_instance_of_expected_type() {
throwables.assertHasRootCauseExactlyInstanceOf(someInfo(), throwableWithCause, IllegalArgumentException.class);
throwables.assertHasRootCauseExactlyInstanceOf(INFO, throwableWithCause, IllegalArgumentException.class);
}

@Test
void should_fail_if_actual_is_null() {
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> throwables.assertHasRootCauseExactlyInstanceOf(someInfo(), null, IllegalArgumentException.class))
.withMessage(actualIsNull());
// GIVEN
Throwable actual = null;
// WHEN
AssertionError error = expectAssertionError(() -> throwables.assertHasRootCauseExactlyInstanceOf(INFO, actual,
IOException.class));
// THEN
then(error).hasMessage(actualIsNull());
}

@Test
void should_throw_NullPointerException_if_given_type_is_null() {
assertThatNullPointerException().isThrownBy(() -> throwables.assertHasRootCauseExactlyInstanceOf(someInfo(),
throwableWithCause,
null))
.withMessage("The given type should not be null");
// GIVEN
Class<? extends Throwable> type = null;
// WHEN
Throwable throwable = catchThrowable(() -> throwables.assertHasRootCauseExactlyInstanceOf(INFO, throwableWithCause, type));
// THEN
then(throwable).isInstanceOf(NullPointerException.class)
.hasMessage("The given type should not be null");
}

@Test
void should_fail_if_actual_has_no_cause() {
AssertionInfo info = someInfo();
// GIVEN
Class<NullPointerException> expectedCauseType = NullPointerException.class;

Throwable error = catchThrowable(() -> throwables.assertHasRootCauseExactlyInstanceOf(info, actual, expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveRootCauseExactlyInstance(actual, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasRootCauseExactlyInstanceOf(INFO, actual, expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveRootCauseExactlyInstance(actual, expectedCauseType));
}

@Test
void should_fail_if_root_cause_is_not_instance_of_expected_type() {
AssertionInfo info = someInfo();
// GIVEN
Class<NullPointerException> expectedCauseType = NullPointerException.class;

Throwable error = catchThrowable(() -> throwables.assertHasRootCauseExactlyInstanceOf(info, throwableWithCause, expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveRootCauseExactlyInstance(throwableWithCause, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasRootCauseExactlyInstanceOf(INFO, throwableWithCause, expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveRootCauseExactlyInstance(throwableWithCause, expectedCauseType));
}

@Test
void should_fail_if_cause_is_not_exactly_instance_of_expected_type() {
AssertionInfo info = someInfo();
// GIVEN
Class<RuntimeException> expectedCauseType = RuntimeException.class;

Throwable error = catchThrowable(() -> throwables.assertHasRootCauseExactlyInstanceOf(info, throwableWithCause, expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveRootCauseExactlyInstance(throwableWithCause, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasRootCauseExactlyInstanceOf(INFO, throwableWithCause, expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveRootCauseExactlyInstance(throwableWithCause, expectedCauseType));
}
}

0 comments on commit 9739d69

Please sign in to comment.