The preferred assertion library for Geode is AssertJ (see About Unit Testing), which offers a wide range of flexible assertions. The import statement needed to use AssertJ asserts is

import static org.assertj.core.api.Assertions.assertThat;

Here are some examples that may be useful when writing tests:

Simple assertions:

Boolean condition = true;

// Assert that an object is not null
assertThat(condition).isNotNull();

// Assert that an object is an instance of a given class
assertThat(condition).isInstanceOf(Boolean.class);

// Assert that an object is an instance of one of a given number of classes
assertThat(condition).isInstanceOfAny(Boolean.class, Integer.class, Long.class);

// Assert that an object is *exactly* an instance of the specified class (rather than a subclass)
assertThat(new ArrayList<Integer>).isExactlyInstanceOf(ArrayList.class);
// NOTE: The below assertion will fail
assertThat(new ArrayList<Integer>).isExactlyInstanceOf(List.class);

// Assert the value of a boolean
assertThat(condition).isTrue();

int[] arrayOne = {1, 2};
int[] arrayTwo = {1, 2};

// Assert that two objects are equal, using .equals() comparison
assertThat(arrayOne).isEqualTo(arrayTwo);

// Assert that two objects refer to the same object in memory, using == comparison
// NOTE: The below assertion will fail
assertThat(arrayOne).isSameAs(arrayTwo); 

int actual = 1;

// Assert that a value is greater than a given value
assertThat(actual).isGreaterThan(0);

// Assert that a value is less than a given value
assertThat(actual).isLessThan(2);

// Assert that a value falls within a range.
assertThat(actual).isBetween(0, 2);

// Use satisfies() to make multiple assertions without needing to define a local variable
assertThat(Dictionary.getLanguage("English").getAlphabet().toString()).satisfies(alphabet -> {
      assertThat(alphabet.length()).isEqualTo(26);
      assertThat(alphabet.startsWith("a")).isTrue();
      assertThat(alphabet.endsWith("z")).isTrue();
      assertThat(alphabet.indexOf("ø")).isEqualTo(-1);
  }
);

Assertions on Collections:

List<Integer> intList = Arrays.asList(1, 2, 3, 3);

// Assert that a collection contains elements that match the given value(s)
assertThat(intList).contains(2, 3);

// Assert that a collection contains only elements that match the given values and nothing else
assertThat(intList).containsOnly(1, 2, 3);

// Assert that a collection contains the given element exactly once
assertThat(intList).containsOnlyOnce(1);

// Assert that a collection contains the given sequence of entries
assertThat(intList).containsSequence(2, 3, 3);

// Assert that a collection contains exactly the given values, ignoring ordering
assertThat(intList).containsExactlyInAnyOrder(3, 3, 2, 1);

// Assert that a collection contains exactly the given values, in order
assertThat(intList).containsExactly(1, 2, 3, 3);

// Assert that all the elements of a collection satisfy the given assertions
assertThat(intList).allSatisfy(value -> {
  assertThat(value).isGreaterThan(0);
  assertThat(value).isLessThan(4);
});

// Assert that a collection contains all the elements of another collection
assertThat(intList).containsAll(Arrays.asList(3, 1));

// Assert that the contents of two collections are equal, ignoring ordering
assertThat(intList).containsExactlyInAnyOrderElementsOf(Arrays.asList(3, 2, 1, 3));

// Assert that the contents of two collections are equal and in the same order
assertThat(intList).containsExactlyElementsOf(Arrays.asList(1, 2, 3, 3));

Assertions about exceptions:

public void throwException() {
  Exception rootException = new NullPointerException("root message");
  Exception causeException = new UnsupportedOperationException("cause message", rootException);
  throw new IllegalArgumentException("thrown message", intermediateException);
}

// Assert various conditions based on expected exceptions. When asserting multiple conditions,
// it is preferable to put each on its own line for readability
assertThatThrownBy(() -> throwException())
    .isInstanceOf(IllegalArgumentException.class)
    .hasMessageContaining("thrown")
    .hasCauseInstanceOf(UnsupportedOperationException.class)
    .hasStackTraceContaining("cause message")
    .hasRootCauseInstanceOf(NullPointerException.class)
    .hasRootCauseMessage("root message");

Assertions using OR logic:

List<Integer> intList = Arrays.asList(1, 2);

// Assert that at least one of a number of conditions are true, in this case that intList has a 
// size of either 0, 2 or 4
assertThat(intList).satisfiesAnyOf(
    list -> assertThat(list).isEmpty(),
    list -> assertThat(list.size()).isEqualTo(2),
    list -> assertThat(list.size()).isEqualTo(4));

More descriptive messages when assertions fail

Using as() to add context:

The default output when an assertion fails can sometimes be vague or unhelpful. Some methods exist in the AssertJ library that allow the output to be modified to be more informative.

// The default output from this assertion if it fails is vague and unhelpful when determining 
// what the actual cause of the failure was
assertThat(person.isCommitter()).isTrue();

The above assertion produces the following output:

org.junit.ComparisonFailure: 
Expecting value to be true but was false 
Expected :true
Actual   :false

The as() method allows for clarifying details to be added:

// Using as() allows for a description to be added to the condition following it, allowing for
// additional context to be provided to assertions that may otherwise be unclear
assertThat(person.isCommitter()).as("expected isCommitter() to return true").isTrue();

The above assertion produces the following output:

org.junit.ComparisonFailure: [expected isCommitter() to return true] 
Expecting value to be true but was false 
Expected :true
Actual   :false

Using withFailMessage() to override the default error output:

When comparing collections, certain assertions can produce large and potentially unhelpful output upon failure:

List<Integer> intListOne = IntStream.range(0, 1000).boxed().collect(Collectors.toList());
List<Integer> intListTwo = IntStream.range(1, 1000).boxed().collect(Collectors.toList());

assertThat(intListOne).containsExactlyElementsOf(intListTwo);

The above assertion produces the following output (truncated to save space):

java.lang.AssertionError: 
Expecting:
  [0,
    1,
    ... <--- all 1000 elements listed
    999]
to contain exactly (and in same order):
  [1,
    2,
    ... <--- all 999 elements listed
    999]
but some elements were not expected:
  [0]

Using withFailMessage(), the error message for the assertion can be overridden entirely to provide a more succinct and readable message:

List<Integer> intListOne = IntStream.range(0, 1000).boxed().collect(Collectors.toList());
List<Integer> intListTwo = IntStream.range(1, 1000).boxed().collect(Collectors.toList());

assertThat(intListOne)
    .withFailMessage(
        "Contents of intListOne did not exactly match contents of intListTwo. Unexpected elements: %s",
        CollectionUtils.disjunction(intListOne, intListTwo))
    .containsExactlyElementsOf(intListTwo);

The above assertion produces the following output:

java.lang.AssertionError: Contents of intListOne did not exactly match contents of intListTwo. Unexpected elements: [0]
  • No labels