org.kiwiproject.test.assertj.KiwiAssertJ Maven / Gradle / Ivy
package org.kiwiproject.test.assertj;
import static org.assertj.core.api.Assertions.assertThat;
import lombok.experimental.UtilityClass;
import org.assertj.core.api.ObjectAssert;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
/**
* Some AssertJ test utilities that you might or might find useful.
*/
@UtilityClass
public class KiwiAssertJ {
/**
* Assert the given object has exactly the given type.
*
* Returns the object cast to an instance of that type if the assertion passes, otherwise fails the test.
*
* @param object the object to assert
* @param type the expected type
* @param the expected type parameter
* @return the object cast to an instance of T
*/
public static T assertIsExactType(Object object, Class type) {
assertThat(object).isExactlyInstanceOf(type);
return type.cast(object);
}
/**
* Assert the given object is an instance of the given type, i.e. is the same type or a subtype of the given type.ª
*
* Returns the object cast to an instance of that type if the assertion passes, otherwise fails the test.
*
* @param object the object to assert
* @param type the expected type
* @param the expected type parameter
* @return the object cast to an instance of T
*/
public static T assertIsTypeOrSubtype(Object object, Class type) {
assertThat(object).isInstanceOf(type);
return type.cast(object);
}
/**
* Assert the given Iterable contains exactly one element, and returns {@link ObjectAssert} for further
* AssertJ method chaining.
*
* This is basically just a shortcut for {@code assertThat(iterable).hasSize(1).first()} but that seems to come up
* enough in testing (for me anyway) that I don't want to type it out every time.
*
* @param iterable the Iterable
* @param the type of element
* @return an {@link ObjectAssert} for further method chaining
*/
public static ObjectAssert assertThatOnlyElementIn(Iterable iterable) {
return assertThat(iterable)
.describedAs("Expected exactly one element")
.hasSize(1)
.first();
}
/**
* Assert the given Iterable contains exactly one element, and return that element for further inspection.
*
* @param iterable the Iterable
* @param the type of element
* @return the first element
*/
public static T assertAndGetOnlyElementIn(Iterable iterable) {
assertThat(iterable)
.describedAs("Expected exactly one element")
.hasSize(1);
return iterable.iterator().next();
}
/**
* Assert the given Map contains exactly one entry, and return that entry for further inspection.
*
* @param map the Map
* @param the type of keys
* @param the type of values
* @return the first entry
*/
public static Map.Entry assertAndGetOnlyEntryIn(Map map) {
assertThat(map)
.describedAs("Expected exactly one entry")
.hasSize(1);
return map.entrySet().iterator().next();
}
/**
* Assert the given {@link Optional} contains a value, and return that value if true. Otherwise, the assertion
* fails if the Optional does not contain a value.
*
* This is useful in situations in which you don't want to use AssertJ's Optional assertion methods. One
* specific example is when the Optional contains some JSON or XML, and you want to check that the contained
* value, if present, contains several substrings. Example:
*
* var xml = assertPresentAndGet(xmlOptional);
* assertThat(xml)
* .contains("<name>Alice</name>")
* .contains("<age>42</age>")
* .contains("<state>VA</state>");
*
* You could also do this using the {@link org.assertj.core.api.AbstractOptionalAssert#hasValueSatisfying(Consumer)}
* method in AssertJ and putting the same assertions as above within a lambda. However, we usually find the example
* code shown above to be simpler and easier to read.
*
* @param optional the Optional
* @param the type that the Optional contains
* @return the value
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static T assertPresentAndGet(Optional optional) {
assertThat(optional).isPresent();
return optional.orElseThrow();
}
}