Skip to content

Commit 0a5bf8d

Browse files
authored
Add doesNotReturn to Object assertions (#2453)
1 parent 471e8a8 commit 0a5bf8d

File tree

6 files changed

+103
-19
lines changed

6 files changed

+103
-19
lines changed

src/main/java/org/assertj/core/api/AbstractObjectAssert.java

+28-1
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,8 @@ public SELF hasFieldOrProperty(String name) {
654654
* <p>
655655
* Private fields are matched by default but this can be changed by calling {@link Assertions#setAllowExtractingPrivateFields(boolean) Assertions.setAllowExtractingPrivateFields(false)}.
656656
* <p>
657-
* If you are looking to chain multiple assertions on different properties in a type safe way, consider chaining {@link #returns(Object, Function)} calls.
657+
* If you are looking to chain multiple assertions on different properties in a type safe way, consider chaining
658+
* {@link #returns(Object, Function)} and {@link #doesNotReturn(Object, Function)} calls.
658659
* <p>
659660
* Example:
660661
* <pre><code class='java'> public class TolkienCharacter {
@@ -1093,6 +1094,32 @@ public <T> SELF returns(T expected, Function<ACTUAL, T> from) {
10931094
return myself;
10941095
}
10951096

1097+
/**
1098+
* Verifies that the object under test does not return the given expected value from the given {@link Function},
1099+
* a typical usage is to pass a method reference to assert object's property.
1100+
* <p>
1101+
* Wrapping the given {@link Function} with {@link Assertions#from(Function)} makes the assertion more readable.
1102+
* <p>
1103+
* Example:
1104+
* <pre><code class="java"> // from is not mandatory but it makes the assertions more readable
1105+
* assertThat(frodo).doesNotReturn("Bilbo", from(TolkienCharacter::getName))
1106+
* .doesNotReturn("Bilbo", TolkienCharacter::getName) // no from :(
1107+
* .doesNotReturn(null, from(TolkienCharacter::getRace));</code></pre>
1108+
*
1109+
* @param expected the value the object under test method's call should not return.
1110+
* @param from {@link Function} used to acquire the value to test from the object under test. Must not be {@code null}
1111+
* @param <T> the expected value type the given {@code method} returns.
1112+
* @return {@code this} assertion object.
1113+
* @throws NullPointerException if given {@code from} function is null
1114+
*
1115+
* @since 3.22.0
1116+
*/
1117+
public <T> SELF doesNotReturn(T expected, Function<ACTUAL, T> from) {
1118+
requireNonNull(from, "The given getter method/Function must not be null");
1119+
objects.assertNotEqual(info, from.apply(actual), expected);
1120+
return myself;
1121+
}
1122+
10961123
/**
10971124
* Enable using a recursive field by field comparison strategy when calling the chained {@link RecursiveComparisonAssert#isEqualTo(Object) isEqualTo} assertion.
10981125
* <p>

src/main/java/org/assertj/core/api/Assertions.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2211,13 +2211,14 @@ public static TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
22112211
}
22122212

22132213
/**
2214-
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
2214+
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
2215+
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
22152216
* <p>
22162217
* Example:
22172218
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
22182219
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
22192220
* .returns(2.4, from(Jedi::getHeight))
2220-
* .returns(150, from(Jedi::getWeight)); </code></pre>
2221+
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
22212222
*
22222223
* @param extractor A function to extract test subject's property
22232224
* @param <F> Type of test subject

src/main/java/org/assertj/core/api/BDDAssertions.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2601,13 +2601,14 @@ public static TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
26012601
}
26022602

26032603
/**
2604-
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
2604+
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
2605+
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
26052606
* <p>
26062607
* Example:
26072608
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
26082609
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
26092610
* .returns(2.4, from(Jedi::getHeight))
2610-
* .returns(150, from(Jedi::getWeight)); </code></pre>
2611+
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
26112612
*
26122613
* @param extractor A function to extract test subject's property
26132614
* @param <F> Type of test subject

src/main/java/org/assertj/core/api/WithAssertions.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1772,13 +1772,14 @@ default TemporalUnitOffset byLessThan(long value, TemporalUnit unit) {
17721772
}
17731773

17741774
/**
1775-
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)}.
1775+
* A syntax sugar to write fluent assertion using {@link ObjectAssert#returns(Object, Function)} and
1776+
* {@link ObjectAssert#doesNotReturn(Object, Function)}.
17761777
* <p>
17771778
* Example:
17781779
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
17791780
* assertThat(yoda).returns("Yoda", from(Jedi::getName))
17801781
* .returns(2.4, from(Jedi::getHeight))
1781-
* .returns(150, from(Jedi::getWeight)); </code></pre>
1782+
* .doesNotReturn(null, from(Jedi::getWeight)); </code></pre>
17821783
*
17831784
* @param extractor A function to extract test subject's property
17841785
* @param <F> Type of test subject
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
3+
* the License. You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
* specific language governing permissions and limitations under the License.
10+
*
11+
* Copyright 2012-2021 the original author or authors.
12+
*/
13+
package org.assertj.core.api.object;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.assertj.core.api.Assertions.catchThrowable;
17+
import static org.assertj.core.api.Assertions.from;
18+
import static org.assertj.core.api.BDDAssertions.then;
19+
import static org.mockito.Mockito.verify;
20+
21+
import org.assertj.core.api.ObjectAssert;
22+
import org.assertj.core.api.ObjectAssertBaseTest;
23+
import org.assertj.core.test.Jedi;
24+
import org.junit.jupiter.api.Test;
25+
26+
class ObjectAssert_doesNotReturn_Test extends ObjectAssertBaseTest {
27+
28+
@Override
29+
protected ObjectAssert<Jedi> invoke_api_method() {
30+
return assertions.doesNotReturn("Yoda", Jedi::getName);
31+
}
32+
33+
@Override
34+
protected void verify_internal_effects() {
35+
verify(objects).assertNotEqual(getInfo(assertions), getActual(assertions).getName(), "Yoda");
36+
}
37+
38+
@Test
39+
void should_fail_with_throwing_NullPointerException_if_method_is_null() {
40+
// WHEN
41+
Throwable thrown = catchThrowable(() -> assertions.doesNotReturn("May the force be with you.", null));
42+
// THEN
43+
then(thrown).isInstanceOf(NullPointerException.class)
44+
.hasMessage("The given getter method/Function must not be null");
45+
}
46+
47+
@Test
48+
void perform_assertion_like_users() {
49+
// GIVEN
50+
Jedi yoda = new Jedi("Yoda", "Green");
51+
// WHEN/THEN
52+
assertThat(yoda).doesNotReturn("Luke", from(Jedi::getName))
53+
.doesNotReturn("Luke", Jedi::getName);
54+
}
55+
56+
}

src/test/java/org/assertj/core/api/object/ObjectAssert_returns_Test.java

+10-12
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,17 @@
1313
package org.assertj.core.api.object;
1414

1515
import static org.assertj.core.api.Assertions.assertThat;
16-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
16+
import static org.assertj.core.api.Assertions.catchThrowable;
1717
import static org.assertj.core.api.Assertions.from;
18+
import static org.assertj.core.api.BDDAssertions.then;
1819
import static org.mockito.Mockito.verify;
1920

20-
import java.util.function.Function;
21-
22-
import org.assertj.core.api.AbstractObjectAssert;
2321
import org.assertj.core.api.ObjectAssert;
2422
import org.assertj.core.api.ObjectAssertBaseTest;
25-
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
2623
import org.assertj.core.test.Jedi;
2724
import org.junit.jupiter.api.Test;
2825

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

4641
@Test
4742
void should_fail_with_throwing_NullPointerException_if_method_is_null() {
48-
ThrowingCallable code = () -> assertions.returns("May the force be with you.", null);
49-
assertThatThrownBy(code).isExactlyInstanceOf(NullPointerException.class)
50-
.hasMessage("The given getter method/Function must not be null");
43+
// WHEN
44+
Throwable thrown = catchThrowable(() -> assertions.returns("May the force be with you.", null));
45+
// THEN
46+
then(thrown).isInstanceOf(NullPointerException.class)
47+
.hasMessage("The given getter method/Function must not be null");
5148
}
5249

5350
@Test
5451
void perform_assertion_like_users() {
55-
52+
// GIVEN
5653
Jedi yoda = new Jedi("Yoda", "Green");
54+
// WHEN/THEN
5755
assertThat(yoda).returns("Yoda", from(Jedi::getName))
5856
.returns("Yoda", Jedi::getName);
59-
6057
}
58+
6159
}

0 commit comments

Comments
 (0)