Skip to content

Commit

Permalink
Add doesNotReturn to Object assertions (#2453)
Browse files Browse the repository at this point in the history
  • Loading branch information
scordio committed Dec 31, 2021
1 parent 471e8a8 commit 0a5bf8d
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 19 deletions.
29 changes: 28 additions & 1 deletion src/main/java/org/assertj/core/api/AbstractObjectAssert.java
Expand Up @@ -654,7 +654,8 @@ public SELF hasFieldOrProperty(String name) {
* <p>
* Private fields are matched by default but this can be changed by calling {@link Assertions#setAllowExtractingPrivateFields(boolean) Assertions.setAllowExtractingPrivateFields(false)}.
* <p>
* If you are looking to chain multiple assertions on different properties in a type safe way, consider chaining {@link #returns(Object, Function)} calls.
* If you are looking to chain multiple assertions on different properties in a type safe way, consider chaining
* {@link #returns(Object, Function)} and {@link #doesNotReturn(Object, Function)} calls.
* <p>
* Example:
* <pre><code class='java'> public class TolkienCharacter {
Expand Down Expand Up @@ -1093,6 +1094,32 @@ public <T> SELF returns(T expected, Function<ACTUAL, T> from) {
return myself;
}

/**
* Verifies that the object under test does not return the given expected value from the given {@link Function},
* a typical usage is to pass a method reference to assert object's property.
* <p>
* Wrapping the given {@link Function} with {@link Assertions#from(Function)} makes the assertion more readable.
* <p>
* Example:
* <pre><code class="java"> // from is not mandatory but it makes the assertions more readable
* assertThat(frodo).doesNotReturn("Bilbo", from(TolkienCharacter::getName))
* .doesNotReturn("Bilbo", TolkienCharacter::getName) // no from :(
* .doesNotReturn(null, from(TolkienCharacter::getRace));</code></pre>
*
* @param expected the value the object under test method's call should not return.
* @param from {@link Function} used to acquire the value to test from the object under test. Must not be {@code null}
* @param <T> the expected value type the given {@code method} returns.
* @return {@code this} assertion object.
* @throws NullPointerException if given {@code from} function is null
*
* @since 3.22.0
*/
public <T> SELF doesNotReturn(T expected, Function<ACTUAL, T> from) {
requireNonNull(from, "The given getter method/Function must not be null");
objects.assertNotEqual(info, from.apply(actual), expected);
return myself;
}

/**
* Enable using a recursive field by field comparison strategy when calling the chained {@link RecursiveComparisonAssert#isEqualTo(Object) isEqualTo} assertion.
* <p>
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/assertj/core/api/Assertions.java
Expand Up @@ -2211,13 +2211,14 @@ public static TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
}

/**
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
* <p>
* Example:
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
* .returns(2.4, from(Jedi::getHeight))
* .returns(150, from(Jedi::getWeight)); </code></pre>
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
*
* @param extractor A function to extract test subject's property
* @param <F> Type of test subject
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/assertj/core/api/BDDAssertions.java
Expand Up @@ -2601,13 +2601,14 @@ public static TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
}

/**
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
* <p>
* Example:
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
* .returns(2.4, from(Jedi::getHeight))
* .returns(150, from(Jedi::getWeight)); </code></pre>
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
*
* @param extractor A function to extract test subject's property
* @param <F> Type of test subject
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/assertj/core/api/WithAssertions.java
Expand Up @@ -1772,13 +1772,14 @@ default TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
}

/**
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
* <p>
* Example:
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
* .returns(2.4, from(Jedi::getHeight))
* .returns(150, from(Jedi::getWeight)); </code></pre>
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
*
* @param extractor A function to extract test subject's property
* @param <F> Type of test subject
Expand Down
@@ -0,0 +1,56 @@
/*
* 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-2021 the original author or authors.
*/
package org.assertj.core.api.object;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.Assertions.from;
import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.Mockito.verify;

import org.assertj.core.api.ObjectAssert;
import org.assertj.core.api.ObjectAssertBaseTest;
import org.assertj.core.test.Jedi;
import org.junit.jupiter.api.Test;

class ObjectAssert_doesNotReturn_Test extends ObjectAssertBaseTest {

@Override
protected ObjectAssert<Jedi> invoke_api_method() {
return assertions.doesNotReturn("Yoda", Jedi::getName);
}

@Override
protected void verify_internal_effects() {
verify(objects).assertNotEqual(getInfo(assertions), getActual(assertions).getName(), "Yoda");
}

@Test
void should_fail_with_throwing_NullPointerException_if_method_is_null() {
// WHEN
Throwable thrown = catchThrowable(() -> assertions.doesNotReturn("May the force be with you.", null));
// THEN
then(thrown).isInstanceOf(NullPointerException.class)
.hasMessage("The given getter method/Function must not be null");
}

@Test
void perform_assertion_like_users() {
// GIVEN
Jedi yoda = new Jedi("Yoda", "Green");
// WHEN/THEN
assertThat(yoda).doesNotReturn("Luke", from(Jedi::getName))
.doesNotReturn("Luke", Jedi::getName);
}

}
Expand Up @@ -13,22 +13,17 @@
package org.assertj.core.api.object;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.Assertions.from;
import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.Mockito.verify;

import java.util.function.Function;

import org.assertj.core.api.AbstractObjectAssert;
import org.assertj.core.api.ObjectAssert;
import org.assertj.core.api.ObjectAssertBaseTest;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.assertj.core.test.Jedi;
import org.junit.jupiter.api.Test;

/**
* Tests for <code>{@link AbstractObjectAssert#returns(Object, Function)}</code>.
*
* @author Takuya "Mura-Mi" Murakami
*/
class ObjectAssert_returns_Test extends ObjectAssertBaseTest {
Expand All @@ -45,17 +40,20 @@ protected void verify_internal_effects() {

@Test
void should_fail_with_throwing_NullPointerException_if_method_is_null() {
ThrowingCallable code = () -> assertions.returns("May the force be with you.", null);
assertThatThrownBy(code).isExactlyInstanceOf(NullPointerException.class)
.hasMessage("The given getter method/Function must not be null");
// WHEN
Throwable thrown = catchThrowable(() -> assertions.returns("May the force be with you.", null));
// THEN
then(thrown).isInstanceOf(NullPointerException.class)
.hasMessage("The given getter method/Function must not be null");
}

@Test
void perform_assertion_like_users() {

// GIVEN
Jedi yoda = new Jedi("Yoda", "Green");
// WHEN/THEN
assertThat(yoda).returns("Yoda", from(Jedi::getName))
.returns("Yoda", Jedi::getName);

}

}

0 comments on commit 0a5bf8d

Please sign in to comment.