Skip to content

Commit

Permalink
Retain assertion state in asInstanceOf()
Browse files Browse the repository at this point in the history
  • Loading branch information
scordio authored and joel-costigliola committed Jun 22, 2019
1 parent 9649c1f commit a2fe4b2
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 38 deletions.
8 changes: 6 additions & 2 deletions src/main/java/org/assertj/core/api/AbstractAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.error.ShouldMatch.shouldMatch;
import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull;
import static org.assertj.core.util.Preconditions.checkArgument;
import static org.assertj.core.util.Strings.formatIfArgs;

Expand Down Expand Up @@ -366,10 +367,13 @@ public SELF satisfies(Condition<? super ACTUAL> condition) {
}

/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
@CheckReturnValue
public <ASSERT extends Assert<?, ?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?, ASSERT> instanceOfAssertFactory) {
return instanceOfAssertFactory.createAssert(actual);
public <ASSERT extends AbstractAssert<?, ?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?, ASSERT> instanceOfAssertFactory) {
requireNonNull(instanceOfAssertFactory, shouldNotBeNull("instanceOfAssertFactory").create());
objects.assertIsInstanceOf(info, actual, instanceOfAssertFactory.getType());
return (ASSERT) instanceOfAssertFactory.createAssert(actual).withAssertionState(myself);
}

/** {@inheritDoc} */
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/assertj/core/api/Assert.java
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
*
* @since 3.13.0
*/
<ASSERT extends Assert<?, ?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?, ASSERT> instanceOfAssertFactory);
<ASSERT extends AbstractAssert<?, ?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?, ASSERT> instanceOfAssertFactory);

/**
* Verifies that the actual value is an instance of the given type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package org.assertj.core.api;

import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull;

/**
Expand All @@ -25,7 +24,7 @@
* @author Stefano Cordio
* @since 3.13.0
*/
public class InstanceOfAssertFactory<T, ASSERT extends Assert<?, ?>> implements AssertFactory<Object, ASSERT> {
public class InstanceOfAssertFactory<T, ASSERT extends AbstractAssert<?, ?>> implements AssertFactory<Object, ASSERT> {

private final Class<T> type;
private final AssertFactory<T, ASSERT> assertFactory;
Expand All @@ -41,10 +40,13 @@ public InstanceOfAssertFactory(Class<T> type, AssertFactory<T, ASSERT> assertFac
this.assertFactory = requireNonNull(assertFactory, shouldNotBeNull("assertFactory").create());
}

Class<T> getType() {
return type;
}

/** {@inheritDoc} */
@Override
public ASSERT createAssert(Object value) {
assertThat(value).isInstanceOf(type);
return assertFactory.createAssert(type.cast(value));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@

import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldBeInstance.shouldBeInstance;
import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull;
import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
import static org.mockito.BDDMockito.willReturn;

import org.junit.jupiter.api.BeforeEach;
Expand All @@ -31,13 +29,13 @@
@ExtendWith(MockitoExtension.class)
class InstanceOfAssertFactoryTest {

private InstanceOfAssertFactory<Integer, Assert<?, ?>> underTest;
private InstanceOfAssertFactory<Integer, AbstractAssert<?, ?>> underTest;

@Mock
private AssertFactory<Integer, Assert<?, ?>> mockAssertFactory;
private AssertFactory<Integer, AbstractAssert<?, ?>> mockAssertFactory;

@Mock
private Assert<?, ?> mockAssert;
private AbstractAssert<?, ?> mockAssert;

@BeforeEach
void setUp() {
Expand Down Expand Up @@ -79,9 +77,10 @@ void should_throw_assertion_error_if_actual_is_not_an_instance_of_given_type() {
// GIVEN
String value = "string";
// WHEN
AssertionError error = expectAssertionError(() -> underTest.createAssert(value));
Throwable throwable = catchThrowable(() -> underTest.createAssert(value));
// THEN
then(error).hasMessage(shouldBeInstance("string", Integer.class).create());
then(throwable).isInstanceOf(ClassCastException.class)
.hasMessage("Cannot cast %s to %s", value.getClass().getName(), underTest.getType().getName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@
*/
package org.assertj.core.api.abstract_;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.CHAR_SEQUENCE;
import static org.mockito.BDDMockito.willReturn;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.InstanceOfAssertFactories.LONG;
import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull;
import static org.mockito.Mockito.verify;

import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.Assert;
import org.assertj.core.api.AbstractAssertBaseTest;
import org.assertj.core.api.AbstractLongAssert;
import org.assertj.core.api.ConcreteAssert;
import org.assertj.core.api.InstanceOfAssertFactory;
import org.junit.jupiter.api.BeforeEach;
import org.assertj.core.presentation.UnicodeRepresentation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

/**
Expand All @@ -32,39 +34,53 @@
* @author Stefano Cordio
*/
@ExtendWith(MockitoExtension.class)
class AbstractAssert_asInstanceOf_with_instanceOfAssertFactory_Test {
class AbstractAssert_asInstanceOf_with_instanceOfAssertFactory_Test extends AbstractAssertBaseTest {

private AbstractAssert<?, ?> underTest;

@Mock
private InstanceOfAssertFactory<?, ?> mockFactory;
@Override
protected ConcreteAssert invoke_api_method() {
assertions.asInstanceOf(LONG);
return null;
}

@Mock
private Assert<?, ?> mockAssert;
@Override
protected void verify_internal_effects() {
verify(objects).assertIsInstanceOf(getInfo(assertions), getActual(assertions), Long.class);
}

private final Object actual = 6L;
@Override
public void should_return_this() {
// Test disabled since asInstanceOf does not return this.
}

@BeforeEach
void setUp() {
underTest = new ConcreteAssert(actual);
@Test
void should_throw_npe_if_no_factory_is_given() {
// WHEN
Throwable thrown = catchThrowable(() -> assertions.asInstanceOf(null));
// THEN
then(thrown).isInstanceOf(NullPointerException.class)
.hasMessage(shouldNotBeNull("instanceOfAssertFactory").create());
}

@Test
void should_return_factory_result() {
// GIVEN
willReturn(mockAssert).given(mockFactory).createAssert(actual);
void should_return_narrowed_assert_type() {
// WHEN
Assert<?, ?> result = underTest.asInstanceOf(mockFactory);
AbstractAssert<?, ?> result = assertions.asInstanceOf(LONG);
// THEN
assertThat(result).isSameAs(mockAssert);
then(result).isInstanceOf(AbstractLongAssert.class);
}

@Test
public void can_call_narrowed_type_assertions() {
void should_keep_existing_assertion_state() {
// GIVEN
Object value = "abc";
assertions.as("description")
.overridingErrorMessage("error message")
.withRepresentation(new UnicodeRepresentation());
// WHEN
AbstractAssert<?, ?> result = assertions.asInstanceOf(LONG);
// THEN
assertThat(value).asInstanceOf(CHAR_SEQUENCE).startsWith("ab");
then(result).hasFieldOrPropertyWithValue("objects", objects)
.extracting(AbstractAssert::getWritableAssertionInfo)
.isEqualToComparingFieldByField(getInfo(assertions));
}

}

0 comments on commit a2fe4b2

Please sign in to comment.