Skip to content

Commit

Permalink
Add as(InstanceOfAssertFactory) to Assertions and WithAssertions (ass…
Browse files Browse the repository at this point in the history
…ertj#1609)

This improves assertion readability with methods having an
InstanceOfAssertFactory parameter.
  • Loading branch information
scordio authored and joel-costigliola committed Sep 20, 2019
1 parent 7431b8d commit 3cf8cf3
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 15 deletions.
18 changes: 12 additions & 6 deletions src/main/java/org/assertj/core/api/AbstractObjectAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ public AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> extracting(S
* .startsWith(&quot;Fro&quot;);
*
* // To get String assertions, use {@link #extracting(String, InstanceOfAssertFactory)}:
* assertThat(frodo).extracting(&quot;name&quot;, InstanceOfAssertFactories.STRING)
* assertThat(frodo).extracting(&quot;name&quot;, as(InstanceOfAssertFactories.STRING))
* .startsWith(&quot;Fro&quot;);</code></pre>
* <p>
* A property with the given name is looked for first, if it doesn't exist then a field with the given name is looked
Expand Down Expand Up @@ -672,16 +672,19 @@ public AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> extracting(S
* The {@code assertFactory} parameter allows to specify an {@link InstanceOfAssertFactory}, which is used to get the
* assertions narrowed to the factory type.
* <p>
* Wrapping the given {@link InstanceOfAssertFactory} with {@link Assertions#as(InstanceOfAssertFactory)} makes the
* assertion more readable.
* <p>
* Example:
* <pre><code class='java'> // Create frodo, setting its name, age and Race (Race having a name property)
* TolkienCharacter frodo = new TolkienCharacter(&quot;Frodo&quot;, 33, HOBBIT);
*
* // let's extract and verify Frodo's name:
* assertThat(frodo).extracting(&quot;name&quot;, InstanceOfAssertFactories.STRING)
* assertThat(frodo).extracting(&quot;name&quot;, as(InstanceOfAssertFactories.STRING))
* .startsWith(&quot;Fro&quot;);
*
* // The following assertion will fail as Frodo's name is not an Integer:
* assertThat(frodo).extracting(&quot;name&quot;, InstanceOfAssertFactories.INTEGER)
* assertThat(frodo).extracting(&quot;name&quot;, as(InstanceOfAssertFactories.INTEGER))
* .isZero();</code></pre>
* <p>
* A property with the given name is looked for first, if it doesn't exist then a field with the given name is looked
Expand Down Expand Up @@ -759,7 +762,7 @@ public AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> extracting(@
* .startsWith(&quot;Fro&quot;);
*
* // To get String assertions, use {@link #extracting(Function, InstanceOfAssertFactory)}:
* assertThat(frodo).extracting(TolkienCharacter::getName, InstanceOfAssertFactories.STRING)
* assertThat(frodo).extracting(TolkienCharacter::getName, as(InstanceOfAssertFactories.STRING))
* .startsWith(&quot;Fro&quot;);</code></pre>
*
* @param <T> the expected extracted value type.
Expand All @@ -782,16 +785,19 @@ public <T> AbstractObjectAssert<?, T> extracting(Function<? super ACTUAL, T> ext
* The {@code assertFactory} parameter allows to specify an {@link InstanceOfAssertFactory}, which is used to get the
* assertions narrowed to the factory type.
* <p>
* Wrapping the given {@link InstanceOfAssertFactory} with {@link Assertions#as(InstanceOfAssertFactory)} makes the
* assertion more readable.
* <p>
* Example:
* <pre><code class='java'> // Create frodo, setting its name, age and Race
* TolkienCharacter frodo = new TolkienCharacter(&quot;Frodo&quot;, 33, HOBBIT);
*
* // let's extract and verify Frodo's name:
* assertThat(frodo).extracting(TolkienCharacter::getName, InstanceOfAssertFactories.STRING)
* assertThat(frodo).extracting(TolkienCharacter::getName, as(InstanceOfAssertFactories.STRING))
* .startsWith(&quot;Fro&quot;);
*
* // The following assertion will fail as Frodo's name is not an Integer:
* assertThat(frodo).extracting(TolkienCharacter::getName, InstanceOfAssertFactories.INTEGER)
* assertThat(frodo).extracting(TolkienCharacter::getName, as(InstanceOfAssertFactories.INTEGER))
* .isZero();</code></pre>
*
* @param <T> the expected extracted value type
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/org/assertj/core/api/Assertions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,27 @@ public static <F, T> Function<F, T> from(Function<F, T> extractor) {
return extractor;
}

/**
* A syntax sugar to write fluent assertion with methods having an {@link InstanceOfAssertFactory} parameter.
* <p>
* Example:
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
* assertThat(yoda).extracting(Jedi::getName, as(InstanceOfAssertFactories.STRING))
* .startsWith("Yo");</code></pre>
*
* @param assertFactory the factory which verifies the type and creates the new {@code Assert}
* @param <T> the type to use for the cast.
* @param <ASSERT> the type of the resulting {@code Assert}
* @return same instance of {@code assertFactory}
*
* @since 3.14.0
* @see AbstractObjectAssert#extracting(String, InstanceOfAssertFactory)
* @see AbstractObjectAssert#extracting(Function, InstanceOfAssertFactory)
*/
public static <T, ASSERT extends AbstractAssert<?, ?>> InstanceOfAssertFactory<T, ASSERT> as(InstanceOfAssertFactory<T, ASSERT> assertFactory) {
return assertFactory;
}

// ------------------------------------------------------------------------------------------------------
// Condition methods : not assertions but here to have a single entry point to all AssertJ features.
// ------------------------------------------------------------------------------------------------------
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/org/assertj/core/api/WithAssertions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,26 @@ default <F, T> Function<F, T> from(Function<F, T> extractor) {
return Assertions.from(extractor);
}

/**
* A syntax sugar to write fluent assertion with methods having an {@link InstanceOfAssertFactory} parameter.
* <p>
* Example:
* <pre><code class="java"> Jedi yoda = new Jedi("Yoda", "Green");
* assertThat(yoda).extracting(Jedi::getName, as(InstanceOfAssertFactories.STRING))
* .startsWith("Yo");</code></pre>
*
* @param assertFactory the factory which verifies the type and creates the new {@code Assert}
* @param <T> the type to use for the cast.
* @param <ASSERT> the type of the resulting {@code Assert}
* @return same instance of {@code assertFactory}
*
* @since 3.14.0
* @see Assertions#as(InstanceOfAssertFactory)
*/
default <T, ASSERT extends AbstractAssert<?, ?>> InstanceOfAssertFactory<T, ASSERT> as(InstanceOfAssertFactory<T, ASSERT> assertFactory) {
return Assertions.as(assertFactory);
}

/**
* Creates a new <code>{@link AnyOf}</code>
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.assertj.core.api;

import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.Mockito.mock;

import org.junit.jupiter.api.Test;

/**
* Tests for <code>{@link Assertions#as(InstanceOfAssertFactory)}</code>.
*
* @author Stefano Cordio
*/
class Assertions_as_with_InstanceOfAssertFactory_Test {

@Test
@SuppressWarnings("unchecked")
void should_return_the_given_assert_factory() {
// GIVEN
InstanceOfAssertFactory<?, AbstractAssert<?, ?>> assertFactory = mock(InstanceOfAssertFactory.class);
// WHEN
InstanceOfAssertFactory<?, AbstractAssert<?, ?>> result = Assertions.as(assertFactory);
// THEN
then(result).isSameAs(assertFactory);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.assertj.core.api;

import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.Mockito.mock;

import java.util.function.Function;

import org.junit.jupiter.api.Test;

/**
* Tests for <code>{@link Assertions#from(Function)}</code>.
*
* @author Stefano Cordio
*/
class Assertions_from_with_Function_Test {

@Test
void should_return_the_given_extractor() {
// GIVEN
Function<?, ?> extractor = mock(Function.class);
// WHEN
Function<?, ?> result = Assertions.from(extractor);
// THEN
then(result).isSameAs(extractor);
}

}
9 changes: 5 additions & 4 deletions src/test/java/org/assertj/core/api/SoftAssertionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static java.util.Collections.emptyList;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
Expand Down Expand Up @@ -425,7 +426,7 @@ public void should_pass_when_using_extracting_with_object() {
.extracting("first")
.isEqualTo("John");
softly.assertThat(name)
.extracting("first", STRING)
.extracting("first", as(STRING))
.startsWith("Jo");
softly.assertThat(name)
.extracting(Name::getFirst, Name::getLast)
Expand All @@ -434,7 +435,7 @@ public void should_pass_when_using_extracting_with_object() {
.extracting(Name::getFirst)
.isEqualTo("John");
softly.assertThat(name)
.extracting(Name::getFirst, STRING)
.extracting(Name::getFirst, as(STRING))
.startsWith("Jo");
// THEN
assertThat(softly.errorsCollected()).isEmpty();
Expand Down Expand Up @@ -667,7 +668,7 @@ public void should_collect_all_errors_when_using_extracting_on_object() {
.contains("Frodo", 55);
softly.assertThat(frodo)
.overridingErrorMessage("error 3")
.extracting("name", STRING)
.extracting("name", as(STRING))
.startsWith("Bar");
softly.assertThat(frodo)
.overridingErrorMessage("error 4")
Expand All @@ -681,7 +682,7 @@ public void should_collect_all_errors_when_using_extracting_on_object() {
.isEqualTo("Foo");
softly.assertThat(frodo)
.overridingErrorMessage("error 6")
.extracting(TolkienCharacter::getName, STRING)
.extracting(TolkienCharacter::getName, as(STRING))
.startsWith("Bar");
// THEN
assertThat(softly.errorsCollected()).extracting(Throwable::getMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
*/
package org.assertj.core.api;

import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.util.Sets.newLinkedHashSet;
import static org.mockito.Mockito.mock;

import java.io.BufferedInputStream;
import java.io.File;
Expand All @@ -37,6 +39,7 @@
import java.util.OptionalLong;
import java.util.Set;
import java.util.function.DoublePredicate;
import java.util.function.Function;
import java.util.function.IntPredicate;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
Expand Down Expand Up @@ -653,7 +656,7 @@ public void withAssertions_failBecauseExceptionWasNotThrown_Test() {
@Test
public void withAssertions_setAllowExtractingPrivateFields_Test() {
setAllowExtractingPrivateFields(false);
//reset to default
// reset to default
setAllowExtractingPrivateFields(true);
}

Expand Down Expand Up @@ -796,4 +799,26 @@ public void withAssertions_assertThat_url_Test() throws MalformedURLException {
public void withAssertions_assertThat_uri_Test() {
assertThat(java.net.URI.create("https://github.com/joel-costigliola/assertj-core")).hasHost("github.com");
}

@Test
void withAssertions_from_function_Test() {
// GIVEN
Function<?, ?> extractor = mock(Function.class);
// WHEN
Function<?, ?> result = from(extractor);
// THEN
then(result).isSameAs(extractor);
}

@Test
@SuppressWarnings("unchecked")
void withAssertions_as_instanceOfAssertFactory_Test() {
// GIVEN
InstanceOfAssertFactory<?, AbstractAssert<?, ?>> assertFactory = mock(InstanceOfAssertFactory.class);
// WHEN
InstanceOfAssertFactory<?, AbstractAssert<?, ?>> result = as(assertFactory);
// THEN
then(result).isSameAs(assertFactory);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.assertj.core.api.assumptions;

import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.assertj.core.api.InstanceOfAssertFactories.STRING;
import static org.assertj.core.api.assumptions.BaseAssumptionRunner.assumptionRunner;
Expand Down Expand Up @@ -42,9 +43,9 @@ public static Stream<AssumptionRunner<?>> provideAssumptionsRunners() {
value -> assumeThat(value).extracting(TolkienCharacter::getName)
.isEqualTo("Gandalf")),
assumptionRunner(TolkienCharacter.of("Frodo", 33, Race.HOBBIT),
value -> assumeThat(value).extracting(TolkienCharacter::getName, STRING)
value -> assumeThat(value).extracting(TolkienCharacter::getName, as(STRING))
.startsWith("Fro"),
value -> assumeThat(value).extracting(TolkienCharacter::getName, STRING)
value -> assumeThat(value).extracting(TolkienCharacter::getName, as(STRING))
.startsWith("Gan")),
assumptionRunner(TolkienCharacter.of("Frodo", 33, Race.HOBBIT),
value -> assumeThat(value).extracting("name", "age")
Expand All @@ -57,9 +58,9 @@ public static Stream<AssumptionRunner<?>> provideAssumptionsRunners() {
value -> assumeThat(value).extracting("name")
.isEqualTo("Gandalf")),
assumptionRunner(TolkienCharacter.of("Frodo", 33, Race.HOBBIT),
value -> assumeThat(value).extracting("name", STRING)
value -> assumeThat(value).extracting("name", as(STRING))
.startsWith("Fro"),
value -> assumeThat(value).extracting("name", STRING)
value -> assumeThat(value).extracting("name", as(STRING))
.startsWith("Gan")));
}

Expand Down

0 comments on commit 3cf8cf3

Please sign in to comment.