Skip to content

Commit

Permalink
Add anyOf(ThrowingConsumer...) and allOf(ThrowingConsumer...) (#3219
Browse files Browse the repository at this point in the history
)
  • Loading branch information
scordio committed Oct 16, 2023
1 parent e2c418b commit 86f8b58
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 3 deletions.
30 changes: 30 additions & 0 deletions assertj-core/src/main/java/org/assertj/core/api/Assertions.java
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,21 @@ public static <T> Condition<T> allOf(Iterable<? extends Condition<? super T>> co
return AllOf.allOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfies(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SafeVarargs
public static <T> ThrowingConsumer<T> allOf(ThrowingConsumer<? super T>... consumers) {
return actual -> assertThat(actual).satisfies(consumers);
}

/**
* Only delegate to {@link AnyOf#anyOf(Condition...)} so that Assertions offers a full feature entry point to all
* AssertJ features (but you can use {@link AnyOf} if you prefer).
Expand Down Expand Up @@ -2650,6 +2665,21 @@ public static <T> Condition<T> anyOf(Iterable<? extends Condition<? super T>> co
return AnyOf.anyOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfiesAnyOf(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SafeVarargs
public static <T> ThrowingConsumer<T> anyOf(ThrowingConsumer<? super T>... consumers) {
return actual -> assertThat(actual).satisfiesAnyOf(consumers);
}

/**
* Creates a new <code>{@link DoesNotHave}</code>.
*
Expand Down
30 changes: 30 additions & 0 deletions assertj-core/src/main/java/org/assertj/core/api/BDDAssertions.java
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,21 @@ public static <T> Condition<T> allOf(Iterable<? extends Condition<? super T>> co
return Assertions.allOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfies(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SafeVarargs
public static <T> ThrowingConsumer<T> allOf(ThrowingConsumer<? super T>... consumers) {
return Assertions.allOf(consumers);
}

/**
* Only delegate to {@link AnyOf#anyOf(Condition...)} so that Assertions offers a full feature entry point to all
* AssertJ features (but you can use {@link AnyOf} if you prefer).
Expand Down Expand Up @@ -3183,6 +3198,21 @@ public static <T> Condition<T> anyOf(Iterable<? extends Condition<? super T>> co
return Assertions.anyOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfiesAnyOf(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SafeVarargs
public static <T> ThrowingConsumer<T> anyOf(ThrowingConsumer<? super T>... consumers) {
return Assertions.anyOf(consumers);
}

/**
* Creates a new <code>{@link DoesNotHave}</code>.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
/**
* {@link Consumer} that deals with checked exceptions by rethrowing them as {@link RuntimeException}.
* <p>
* More precisely, {@link RuntimeException} and {@link AssertionError} are rethrown as they are while any other {@link Throwable} are rethrown as {@link RuntimeException}.
* More precisely, {@link RuntimeException} and {@link AssertionError} are rethrown as they are,
* while any other {@link Throwable} is wrapped in a {@link RuntimeException} and rethrown.
*
* @param <T> consumed type
*/
Expand All @@ -36,4 +37,5 @@ default void accept(final T input) {
}

void acceptThrows(T input) throws Throwable;

}
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,21 @@ default <T> Condition<T> allOf(final Condition<? super T>... conditions) {
return Assertions.allOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfies(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SuppressWarnings("unchecked")
default <T> ThrowingConsumer<T> allOf(ThrowingConsumer<? super T>... consumers) {
return Assertions.allOf(consumers);
}

/**
* Creates a new instance of <code>{@link ObjectArrayAssert}</code>.
*
Expand Down Expand Up @@ -1966,6 +1981,21 @@ default <T> Condition<T> anyOf(final Condition<? super T>... conditions) {
return Assertions.anyOf(conditions);
}

/**
* Create a new <code>{@link ThrowingConsumer}</code> that delegates the evaluation of the
* given consumers to {@link AbstractAssert#satisfiesAnyOf(ThrowingConsumer[])}.
*
* @param <T> the type of object the given consumers accept
* @param consumers the consumers to evaluate
* @return the {@code ThrowingConsumer} instance
*
* @since 3.25.0
*/
@SuppressWarnings("unchecked")
default <T> ThrowingConsumer<T> anyOf(ThrowingConsumer<? super T>... consumers) {
return Assertions.anyOf(consumers);
}

/**
* Creates a new <code>{@link DoesNotHave}</code>.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.api;

import static org.assertj.core.api.Assertions.allOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.util.AssertionsUtil.expectAssertionError;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.ValueSource;
import org.opentest4j.MultipleFailuresError;

class Assertions_allOf_with_ThrowingConsumer_Test {

@Test
void should_pass_if_all_consumers_pass() {
// GIVEN
ThrowingConsumer<String> underTest = allOf(e -> assertThat(e).isNotNull(),
e -> assertThat(e).isNotBlank());
// WHEN/THEN
underTest.accept("value");
}

@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = "value")
void should_fail_if_any_consumer_fails(String value) {
// GIVEN
ThrowingConsumer<String> underTest = allOf(e -> assertThat(e).isBlank(),
e -> assertThat(e).isNotBlank());
// WHEN
AssertionError assertionError = expectAssertionError(() -> underTest.accept(value));
// THEN
then(assertionError).isInstanceOf(MultipleFailuresError.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.api;

import static org.assertj.core.api.Assertions.anyOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.util.AssertionsUtil.expectAssertionError;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.ValueSource;
import org.opentest4j.MultipleFailuresError;

class Assertions_anyOf_with_ThrowingConsumer_Test {

@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = "value")
void should_pass_if_any_consumer_passes(String value) {
// GIVEN
ThrowingConsumer<String> underTest = anyOf(e -> assertThat(e).isBlank(),
e -> assertThat(e).isNotBlank());
// WHEN/THEN
underTest.accept(value);
}

@Test
void should_fail_if_all_consumers_fail() {
// GIVEN
ThrowingConsumer<String> underTest = anyOf(e -> assertThat(e).isNotNull(),
e -> assertThat(e).isNotBlank());
// WHEN
AssertionError assertionError = expectAssertionError(() -> underTest.accept(null));
// THEN
then(assertionError).isInstanceOf(MultipleFailuresError.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,15 @@ private static Stream<Arguments> standard_and_bdd_assertion_methods() {
}

private static Set<Method> non_assertThat_methodsOf(Method[] declaredMethods) {
return stream(declaredMethods).filter(method -> !method.getName().startsWith("assert")).collect(toSet());
return stream(declaredMethods).filter(method -> !method.getName().startsWith("assert"))
.filter(method -> !method.isSynthetic())
.collect(toSet());
}

private static Set<Method> non_then_methodsOf(Method[] declaredMethods) {
return stream(declaredMethods).filter(method -> !method.getName().startsWith("then")).collect(toSet());
return stream(declaredMethods).filter(method -> !method.getName().startsWith("then"))
.filter(method -> !method.isSynthetic())
.collect(toSet());
}

private static Set<Method> removeMethods(Set<Method> methods, List<String> methodsToRemove) {
Expand Down

0 comments on commit 86f8b58

Please sign in to comment.