Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add doesNotThrowAnyExceptionExcept to AbstractThrowableAssert #3261

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import static java.lang.String.format;
import static org.assertj.core.error.ShouldNotHaveThrown.shouldNotHaveThrown;
import static org.assertj.core.error.ShouldNotHaveThrownExcept.shouldNotHaveThrownExcept;

import java.util.Arrays;
import java.util.IllegalFormatException;
import java.util.regex.Pattern;

Expand All @@ -37,6 +39,7 @@
* @author Mikhail Mazursky
* @author Jack Gough
* @author Mike Gilchrist
* @author Paweł Baczyński
*/
public abstract class AbstractThrowableAssert<SELF extends AbstractThrowableAssert<SELF, ACTUAL>, ACTUAL extends Throwable>
extends AbstractObjectAssert<SELF, ACTUAL> {
Expand Down Expand Up @@ -843,6 +846,45 @@ public void doesNotThrowAnyException() {
if (actual != null) throw Failures.instance().failure(info, shouldNotHaveThrown(actual));
}

/**
* Verifies that the {@link org.assertj.core.api.ThrowableAssert.ThrowingCallable} didn't raise a throwable
* except matching the provided type(s).
* <p>
* Example :
* <pre><code class='java'>
* void foo() {
* throw new IllegalArgumentException();
* }
*
* void bar() {
* }
*
* // assertions succeed:
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept(RuntimeException.class);
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept(IllegalArgumentException.class);
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept(IllegalArgumentException.class, IllegalStateException.class);
* assertThatCode(() -&gt; bar()).doesNotThrowAnyExceptionExcept();
* assertThatCode(() -&gt; bar()).doesNotThrowAnyExceptionExcept(RuntimeException.class);
*
* // assertions fails:
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept();
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept(IllegalStateException.class);
* assertThatCode(() -&gt; foo()).doesNotThrowAnyExceptionExcept(NumberFormatException.class);</code></pre>
*
* @param exceptionTypes types allowed to be thrown.
* @throws AssertionError if the actual statement raised a {@code Throwable} with type other than provided one(s).
* @since 3.25.0
*/
@SafeVarargs
public final void doesNotThrowAnyExceptionExcept(Class<? extends Throwable>... exceptionTypes) {
if (isNotAnyOf(exceptionTypes)) throw Failures.instance().failure(info, shouldNotHaveThrownExcept(actual, exceptionTypes));
}

private boolean isNotAnyOf(Class<? extends Throwable>[] exceptionTypes) {
if (actual == null) return false;
return Arrays.stream(exceptionTypes).noneMatch(ex -> ex.isAssignableFrom(actual.getClass()));
}

/**
* A shortcut for <code>extracting(Throwable::getMessage, as(InstanceOfAssertFactories.STRING))</code> which allows
* to extract a throwable's message and then execute assertions on it.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 org.assertj.core.util.Throwables.getStackTrace;

public class ShouldNotHaveThrownExcept extends BasicErrorMessageFactory {

@SafeVarargs
public static ErrorMessageFactory shouldNotHaveThrownExcept(Throwable throwable,
Class<? extends Throwable>... throwableClasses) {
return new ShouldNotHaveThrownExcept(throwable, throwableClasses);
}

private ShouldNotHaveThrownExcept(Throwable throwable, Class<? extends Throwable>[] throwableClasses) {
super("%nExpecting code not to raise a throwable except%n %s%nbut caught%n %s",
throwableClasses, getStackTrace(throwable));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.error.ShouldNotHaveThrown.shouldNotHaveThrown;
import static org.assertj.core.error.ShouldNotHaveThrownExcept.shouldNotHaveThrownExcept;

import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test;

import java.io.IOException;

class Assertions_assertThatCode_Test {

@Test
Expand All @@ -44,6 +47,45 @@ void should_fail_when_asserting_no_exception_raised_but_exception_occurs() {
}).withMessage(shouldNotHaveThrown(exception).create());
}

@Test
void should_fail_when_asserting_no_exception_raised_other_than_empty_but_exception_occurs() {
// Given
Exception exception = new Exception("boom");
ThrowingCallable boom = raisingException(exception);

// Expect
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> {
// When;
assertThatCode(boom).doesNotThrowAnyExceptionExcept();
}).withMessage(shouldNotHaveThrownExcept(exception).create());
}

@Test
void should_fail_when_asserting_no_exception_raised_other_than_with_values_but_not_matching_exception_occurs() {
// Given
Exception exception = new IllegalArgumentException("boom");
ThrowingCallable boom = raisingException(exception);

// Expect
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> {
// When;
assertThatCode(boom).doesNotThrowAnyExceptionExcept(IllegalStateException.class, IOException.class);
}).withMessage(shouldNotHaveThrownExcept(exception, IllegalStateException.class, IOException.class).create());
}

@Test
void should_fail_when_asserting_no_exception_raised_other_than_with_values_but_a_subtype_of_that_exception_occurs() {
// Given
Exception exception = new IllegalArgumentException("boom");
ThrowingCallable boom = raisingException(exception);

// Expect
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> {
// When;
assertThatCode(boom).doesNotThrowAnyExceptionExcept(NumberFormatException.class);
}).withMessage(shouldNotHaveThrownExcept(exception, NumberFormatException.class).create());
}

@Test
void can_use_description_in_error_message() {
// Given
Expand Down Expand Up @@ -76,6 +118,44 @@ void should_succeed_when_asserting_no_exception_raised_and_no_exception_occurs()
assertThatCode(silent).doesNotThrowAnyException();
}

@Test
void should_succeed_when_asserting_no_exception_raised_other_than_empty_and_no_exception_occurs() {
// Given
ThrowingCallable silent = () -> {};

// Then
assertThatCode(silent).doesNotThrowAnyExceptionExcept();
}

@Test
void should_succeed_when_asserting_no_exception_raised_except_with_values_and_no_exception_occurs() {
// Given
ThrowingCallable silent = () -> {};

// Then
assertThatCode(silent).doesNotThrowAnyExceptionExcept(IOException.class, IllegalStateException.class);
}

@Test
void should_succeed_when_asserting_no_exception_raised_except_with_values_and_a_matching_exception_occurs() {
// Given
Exception exception = new IllegalArgumentException("boom");
ThrowingCallable boom = raisingException(exception);

// Then
assertThatCode(boom).doesNotThrowAnyExceptionExcept(IOException.class, IllegalArgumentException.class);
}

@Test
void should_succeed_when_asserting_no_exception_raised_except_with_values_and_a_supertype_of_that_exception_occurs() {
// Given
Exception exception = new IllegalArgumentException("boom");
ThrowingCallable boom = raisingException(exception);

// Then
assertThatCode(boom).doesNotThrowAnyExceptionExcept(RuntimeException.class);
}

private ThrowingCallable raisingException(final String reason) {
return raisingException(new Exception(reason));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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 org.assertj.core.description.TextDescription;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static java.lang.String.format;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldNotHaveThrownExcept.shouldNotHaveThrownExcept;
import static org.assertj.core.presentation.StandardRepresentation.STANDARD_REPRESENTATION;
import static org.assertj.core.util.Throwables.getStackTrace;

class ShouldNotHaveThrownExcept_create_Test {

@Test
void should_create_error_message_with_stacktrace_of_exception() {
// GIVEN
Exception exception = new Exception("boom");
ErrorMessageFactory factory = shouldNotHaveThrownExcept(exception, IOException.class, IllegalStateException.class);
// WHEN
String message = factory.create(new TextDescription("Test"), STANDARD_REPRESENTATION);
// THEN
then(message).isEqualTo(format("[Test] %n" +
"Expecting code not to raise a throwable except%n" +
" [java.io.IOException, java.lang.IllegalStateException]%n" +
"but caught%n" +
" \"%s\"", getStackTrace(exception)));
}
}