Conventions for writing new tests and reviewing new/changed tests in this
repository using AssertJ. Use JUnit 5
(org.junit.jupiter.api.*) for test lifecycle and AssertJ for all assertions,
exceptions, and assumptions.
Migrating an existing JUnit 4 test to this style? Start with
migrating-tests.md— it covers the mechanical first pass, the JUnit → AssertJ mapping table, and the post-migration audit. The conventions below define the target style those migrations aim for.
- Use
import static org.assertj.core.api.Assertions.assertThat; - Use
import static org.assertj.core.api.Assertions.assertThatThrownBy;for exception tests - Use
import static org.assertj.core.api.Assertions.assertThatCode;when verifying no exception is thrown - Use
import static org.assertj.core.api.Assumptions.assumeThat;for conditional test execution (skip when assumption fails) — not JUnitAssume, JUnit 5Assumptions, or any other assumption API - Do not import from
AssertionsForClassTypesunless there is a genuine generic ambiguity (e.g.invoke()return values). PreferAssertionsfirst. - Use JUnit 5 (
org.junit.jupiter.api.*) for test lifecycle only —@Test,@BeforeEach,@AfterEach,@TempDir, etc. Use AssertJ for assertions, exceptions, and assumptions.
Use JUnit 5 @TempDir instead of JUnit 4 TemporaryFolder / @Rule:
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.Path;
@TempDir
private Path tempDir;- Declare
@TempDirfieldsprivateby default — not package-private orpublic. - Prefer
java.nio.file.Pathon the test class; expose aprotectedaccessor (e.g.getTempFolder()) when subclasses need the directory. - When both
java.nio.file.Pathandorg.apache.hadoop.fs.Pathare in scope, declare@TempDirasprivate java.nio.file.Path tempDirand do not importjava.nio.file.Pathif it would clash with HadoopPath.
// Wrong — package-private or public
@TempDir
Path tempDir;
// Wrong — JUnit 4
@Rule
public TemporaryFolder temp = new TemporaryFolder();
// Correct
@TempDir
private Path tempDir;
// Correct when Hadoop Path is also used
@TempDir
private java.nio.file.Path tempDir;Stay on java.nio.file.Path for temp-dir work. Convert to Hadoop or java.io.File only at API boundaries.
Hadoop Path from @TempDir:
// Correct — child path for a writer/reader
Path output = new Path(tempDir.resolve("out.parquet").toUri());
// Correct — unique file that must not exist yet (CREATE mode)
Path output = new Path(tempDir.resolve(UUID.randomUUID().toString()).toUri());
// Correct — directory root
Path root = new Path(tempDir.toUri());Prefer .toUri() when constructing Hadoop Path from java.nio.file.Path — do not round-trip through toFile().getAbsolutePath() or toString() on an intermediate variable unless the API requires a String.
java.io.File when required:
File file = tempDir.resolve("child.parquet").toFile();Use tempDir.resolve("name"), not new File(tempDir.toFile(), "name").
Do not pre-create files for Hadoop CREATE-mode writers. Parquet/Hadoop writers open with create-if-not-exists semantics and fail with FileAlreadyExistsException when the path already exists. A UUID (or other unique name) under @TempDir is enough — no Files.createFile / temp.newFile() + delete dance.
// Wrong — creates then deletes, or leaves a file that breaks CREATE
File temp = Files.createTempFile(tempDir, "test", ".tmp").toFile();
Path path = new Path(temp.getAbsolutePath());
java.nio.file.Path tempFile = Files.createFile(tempDir.resolve(UUID.randomUUID().toString()));
Files.delete(tempFile);
Path path = new Path(tempFile.toString());
// Wrong — redundant conversion
new Path(tempDir.toFile().getAbsolutePath())
new Path(new File(tempDir.toFile(), "out").getAbsolutePath())
// Correct — path does not exist yet; writer creates it
Path path = new Path(tempDir.resolve(UUID.randomUUID().toString()).toUri());Files.createTempFile / Files.createTempDirectory: keep only when the test needs JDK temp-name generation inside @TempDir (e.g. a specific prefix/suffix). If the created path is passed to a CREATE-mode writer, delete it first with Files.delete(path). Prefer tempDir.resolve(...) or Files.createTempDirectory(tempDir, "prefix") + new Path(dir.toUri()) over .toFile().getAbsolutePath().
Shared test bases: use org.apache.parquet.DirectWriterTest from the parquet-hadoop test-jar for direct RecordConsumer writing — do not duplicate it in other modules (e.g. no module-local AvroDirectWriterTest).
import org.apache.parquet.DirectWriterTest;
public class TestArrayCompatibility extends DirectWriterTest {AssertJ uses actual first, expected second:
// Correct
assertThat(stream.read()).isEqualTo(124);
assertThat(column("a").compareTo(column("b"))).isEqualTo(-1);
assertThat(cw.getEncoding()).isEqualTo(PLAIN_DICTIONARY);
// Wrong (flipped)
assertThat(124).isEqualTo(stream.read());
assertThat(PLAIN_DICTIONARY).isEqualTo(cw.getEncoding());Use AssertJ assumeThat (import static org.assertj.core.api.Assumptions.assumeThat) to skip tests when a precondition is not met (OS-specific tests, optional features, etc.). Do not use JUnit 4 Assume, JUnit 5 org.junit.jupiter.api.Assumptions, or any JUnit assumption helper.
Prefer fluent assertions on the value under test over wrapping a boolean expression in .isTrue():
// Wrong — JUnit 4
Assume.assumeTrue(System.getProperty("os.name").toLowerCase().startsWith("win"));
// Wrong — JUnit 5
Assumptions.assumeTrue(System.getProperty("os.name").toLowerCase().startsWith("win"));
// Wrong — JUnit 5 static import of Assumptions (still JUnit, not AssertJ)
import static org.junit.jupiter.api.Assumptions.*;
assumeTrue(featureEnabled);
// Correct — AssertJ assumeThat
assumeThat(featureEnabled).isTrue();
// Correct — fluent check on the subject
assumeThat(System.getProperty("os.name").toLowerCase()).startsWith("win");When an assumption fails, AssertJ throws org.opentest4j.TestAbortedException (same as JUnit 5), so the test is reported as skipped.
Use assertThatThrownBy for expected exceptions:
assertThatThrownBy(() -> action())
.isInstanceOf(SomeException.class)
.hasMessage("exact message");Every assertThatThrownBy chain must include .isInstanceOf(...) and a message assertion (.hasMessage, .hasMessageContaining, or .hasMessageStartingWith) unless the thrown exception reliably has a null message (see below).
Always use assertThatThrownBy — not catchThrowable followed by assertThat(caught):
// Wrong — split capture and assertion; does not fail clearly when no exception is thrown
Throwable caught = catchThrowable(() -> action());
assertThat(caught).isInstanceOf(BadConfigurationException.class);
assertThat(caught).hasMessageContaining("23");
// Correct
assertThatThrownBy(() -> action())
.isInstanceOf(BadConfigurationException.class)
.hasMessageContaining("23");Use .satisfies(…), .hasSuppressedException(…), .hasNoSuppressedExceptions(), or .isSameAs(…) on the assertThatThrownBy chain when additional checks on the thrown instance are needed. Reserve catchThrowable only when the test must continue after capturing (e.g. multiple independent actions in one test) — not for a single expected failure.
isInstanceOf alone is not sufficient — it loses coverage of the error text users and operators actually see.
- Always add
.hasMessage(...),.hasMessageContaining(...), or.hasMessageStartingWith(...)when the exception has a non-null message. - Use
.hasMessage(...)when the full message is stable and known (copy it from thethrowsite or a failing test). - Use
.hasMessageContaining(...)when the message includes variable detail (type names, field paths, etc.) or when several loop iterations share a common substring. - Omit
hasMessageonly when the JDK exception message is reliablynull(e.g.EOFException,InvalidMarkException,ReadOnlyBufferException, re-thrown checked exceptions with no message). - Never use
.hasMessage(null)or.hasMessage((String) null).
// Wrong — type only
assertThatThrownBy(() -> new AvroSchemaConverter().convert(parquetSchemaWithInt96))
.isInstanceOf(IllegalArgumentException.class);
// Correct
assertThatThrownBy(() -> new AvroSchemaConverter().convert(parquetSchemaWithInt96))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(
"INT96 is deprecated. As interim enable READ_INT96_AS_FIXED flag to read as byte array.");
// Correct — shared substring across similar failures
assertThatThrownBy(() -> new AvroSchemaConverter().convert(message(type)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Cannot annotate schema");- Do not put
.as("description")onassertThatThrownBychains. Rely on the test method name or inline the intent in the lambda. - Do keep
.as(DECIMAL),.as(logicalType), etc. on builder chains inside the lambda — those are not AssertJ descriptions. - Use an expression lambda for a single action. Reserve block lambdas (
() -> { … }) for multiple statements.
// Wrong — unnecessary block for one call
assertThatThrownBy(() -> {
evaluate(neverCalled);
})
.isInstanceOf(ShortCircuitException.class)
.hasMessage("…");
// Correct — expression lambda (or method reference when it fits)
assertThatThrownBy(() -> evaluate(neverCalled))
.isInstanceOf(ShortCircuitException.class)
.hasMessage("…");
assertThatThrownBy(command::run)
.isInstanceOf(FileAlreadyExistsException.class)
.hasMessageContaining("File already exists");
// Block lambda is fine when setup is required
assertThatThrownBy(() -> {
MessageType incompatible = new MessageType("schema", …);
readGroups(store, originalSchema, incompatible, 1);
})
.isInstanceOf(ParquetDecodingException.class)
.hasMessage("…");// Wrong
assertThatThrownBy(() -> builder.build())
.as("Should reject invalid type")
.isInstanceOf(IllegalArgumentException.class);
// Correct
assertThatThrownBy(() -> builder.build())
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("…");
// Builder .as() inside lambda is fine
assertThatThrownBy(() -> Types.required(INT32).as(DECIMAL).named("x"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("…");Replace no-op assertTrue(true) after a successful call, try/catch/Assert.fail blocks, or Java assert statements with:
assertThatCode(() -> uuidConverter.addBinary(binary)).doesNotThrowAnyException();
assertThatCode(() -> ToolRunner.run(conf, new Main(logger), args)).doesNotThrowAnyException();Prefer dedicated numeric assertions over boolean comparisons:
// Wrong
assertThat(command.run()).isEqualTo(0);
assertThat(0 < file.length()).isTrue();
assertThat(columnSizeInBytes.get("DocId") > columnSizeInBytes.get("Num")).isTrue();
// Correct
assertThat(command.run()).isZero();
assertThat(file.length()).isPositive();
assertThat(columnSizeInBytes.get("DocId")).isGreaterThan(columnSizeInBytes.get("Num"));Use .isZero(), .isPositive(), .isNegative(), .isGreaterThan(...), etc. on the value under test.
// Wrong
assertThat(output.exists()).isTrue();
assertThat(outputFile.length()).isEqualTo(0);
// Correct
assertThat(output).exists();
assertThat(outputFile.length()).isZero();
assertThat(avroFile.length()).isPositive();Use AssertJ's .asString() on the subject, not .toString() in assertThat(...):
// Wrong
assertThat(schema.toString()).isEqualTo(expectedMT.toString());
assertThat(stats.toString()).isEqualTo("min: 1.0, max: 2.0, num_nulls: 0");
// Correct — object compared to object (use .toString() on expected to avoid format overload)
assertThat(schema).asString().isEqualTo(expectedMT.toString());
// Correct — object compared to string literal
assertThat(stats).asString().isEqualTo("min: 1.0, max: 2.0, num_nulls: 0");
assertThat(pred).asString().isEqualTo("or(and(not(…");
assertThat(schemaString).contains("\"name\" : \"timestamp_1\"");
assertThat(schemaString).doesNotContain("\"type\" : [ \"null\", \"INT96\" ]");
// Correct — builder chain
assertThat(Types.required(FIXED_LEN_BYTE_ARRAY).length(16).as(uuidType()).named("uuid_field"))
.asString()
.isEqualTo("required fixed_len_byte_array(16) uuid_field (UUID)");Important: asString().isEqualTo(otherObject) can hit AssertJ's isEqualTo(String format, Object...) overload. When comparing to another object, use .isEqualTo(other.toString()) on the expected side.
.as("description") before .asString() is allowed on normal assertions:
assertThat(records.get(0))
.as("deserialization does not display the same result")
.asString()
.isEqualTo(r1.toString());Prefer AssertJ collection assertions on the collection itself. Assert on the collection (list, conversions, records, encodings, …), not on size(), isEmpty(), or contains() return values.
Always use hasSize(n) instead of assertThat(collection.size()).isEqualTo(n) or assertThat(array.length).isEqualTo(n).
When comparing two collections (or a collection and an array) that should have the same length, prefer hasSameSizeAs over hasSize(other.size()) or hasSize(array.length):
// Wrong
assertThat(splits.size()).isEqualTo(offsets.length);
assertThat(splits).hasSize(sizes.length);
assertThat(actual.size()).isEqualTo(expected.size());
// Correct
assertThat(splits).hasSameSizeAs(offsets);
assertThat(splits).hasSameSizeAs(sizes);
assertThat(actual).hasSameSizeAs(expected);Use hasSizeLessThan / hasSizeGreaterThan when asserting a relative size bound, not a boolean comparison on sizes:
// Wrong
assertThat(result.size() < DATA.size()).isTrue();
// Correct
assertThat(result).hasSizeLessThan(DATA.size());Do not wrap collection state in a boolean and assert with isTrue() / isFalse():
// Wrong
assertThat(column.getEncodings().contains(Encoding.PLAIN_DICTIONARY))
.as("Column should be dictionary encoded: " + name)
.isTrue();
assertThat(column.getEncodings().contains(Encoding.PLAIN))
.as("Column should not have plain data pages" + name)
.isFalse();
assertThat(list).isEqualTo(List.of(1, 2, 3));
assertThat(list).isEqualTo(Collections.emptyList());
assertThat(list.size()).isEqualTo(3);
assertThat(list.isEmpty()).isTrue();
assertThat(!list.isEmpty()).isFalse();
assertThat(list.contains(item)).isTrue();
assertThat(metadata.getBlocks().isEmpty()).isFalse();
assertThat(metadata.getBlocks().size() > 0).isTrue();
// Correct
assertThat(column.getEncodings())
.as("Column should be dictionary encoded: " + name)
.contains(Encoding.PLAIN_DICTIONARY);
assertThat(column.getEncodings())
.as("Column should not have plain data pages" + name)
.doesNotContain(Encoding.PLAIN);
assertThat(list).containsExactly(1, 2, 3);
assertThat(list).isEmpty();
assertThat(list).isNotEmpty();
assertThat(list).hasSize(3);
assertThat(list).contains(item);
assertThat(metadata.getBlocks()).isNotEmpty();Use containsExactly for ordered list equality with literal elements. Use containsExactlyElementsOf when comparing to another iterable. Use containsExactlyInAnyOrder only when order does not matter (e.g. HashSet-backed iterables).
Exception: assertThat(stream.size()).isEqualTo(n) on BytesInput / stream-like types is fine — hasSize() applies to collections, not arbitrary size() methods.
Exception: Statistics.isEmpty(), hasNonNullValue(), and similar domain boolean methods are not Java collections — keep assertThat(stats.isEmpty()).isFalse() or assert the specific stat fields directly.
Assert on the Optional, not on optional.isPresent() / optional.isEmpty() wrapped in isTrue() / isFalse():
// Wrong
assertThat(page.getCrc().isPresent()).as("Checksum was not set in page").isTrue();
assertThat(page.getCrc().isPresent()).as("Checksum was set in page").isFalse();
assertThat(offsetIndex.getUnencodedByteArrayDataBytes(0).isPresent()).isFalse();
// Correct
assertThat(page.getCrc()).as("Checksum was not set in page").isPresent();
assertThat(page.getCrc()).as("Checksum was set in page").isEmpty();
assertThat(offsetIndex.getUnencodedByteArrayDataBytes(0)).isEmpty();For a present value, prefer assertThat(opt).contains(value) or assertThat(opt).get().isEqualTo(value) over assertThat(opt.isPresent()).isTrue() followed by opt.get().
Exception: Statistics.isEmpty() and other domain boolean methods are not Optional — see Collections above.
Replace custom helpers that drain an iterator into a list/array and compare with isEqualTo (e.g. assertIteratorEquals, assertAllRowsEqual). Use AssertJ's IteratorAssert.toIterable() to consume the iterator and apply iterable assertions:
// Wrong — custom helper draining the iterator
static void assertIteratorEquals(PrimitiveIterator.OfInt actualIt, int... expectedValues) {
IntList actualList = new IntArrayList();
actualIt.forEachRemaining(actualList::add);
assertThat(actualList.toIntArray()).isEqualTo(expectedValues);
}
assertIteratorEquals(IndexIterator.all(10), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// Correct — fluent AssertJ on the iterator
assertThat(IndexIterator.all(10)).toIterable().containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
assertThat(IndexIterator.intersection(lhs, rhs)).toIterable().isEmpty();
assertThat(ranges.iterator()).toIterable().containsExactly(1L, 2L, 3L, 4L);Notes:
PrimitiveIterator.OfInt/OfLongextendIterator, soassertThat(iterator)works directly..toIterable()consumes the iterator (same as a drain helper). Non-consuming checks usehasNext()/isExhausted()on the iterator itself (see below).- For
PrimitiveIterator.OfLong,containsExactlyexpectsLongvarargs — useLsuffixes on literals (1L,2L, …). - For
int...expected values passed as a varargs parameter, box before spreading intocontainsExactly:
assertThat(predicate.accept(ci))
.toIterable()
.containsExactly(Arrays.stream(expectedIndexes).boxed().toArray(Integer[]::new));Do not add a custom AssertJ assertion class unless the same pattern is needed across many modules — toIterable() is sufficient.
Assert on the iterator, not on iterator.hasNext() wrapped in isTrue() / isFalse():
// Wrong
assertThat(expIt.hasNext()).isFalse();
assertThat(expIt.hasNext()).isTrue();
// Correct
assertThat(expIt).isExhausted();
assertThat(expIt).hasNext();Use .isExhausted() when all elements were consumed (e.g. after a partial match loop). Use .hasNext() when more elements are expected. .as("…") before these is allowed when the failure message needs context.
AssertJ has no StreamAssert — collect first, then assert on the resulting collection:
// Wrong — boolean wrapper on stream terminal operation
assertThat(result.size() == expected.size()).isTrue();
// Wrong — isEqualTo on two independently collected lists (often fine, but prefer iterable API)
assertThat(result).isEqualTo(DATA.stream().filter(pred).collect(Collectors.toList()));
// Correct — collect actual, then compare as iterable
List<User> result = readFilteredUsers(filter);
assertThat(result).containsExactlyElementsOf(DATA.stream().filter(expectedFilter).collect(Collectors.toList()));
// Correct — known expected elements
assertThat(result).containsExactly(userA, userB);For a Stream used only as an expected source in a helper, passing stream.iterator() to assertThat(it).toIterable() is fine when the stream is consumed once.
When asserting a Java array length, prefer assertThat(array).hasSize(n) over assertThat(array.length).isEqualTo(n).
Prefer one assertion when size and membership are asserted together:
// Wrong — three assertions for the same map
assertThat(map).hasSize(2);
assertThat(map).containsKey(keyA);
assertThat(map).containsKey(keyB);
// Correct
assertThat(map).containsOnlyKeys(keyA, keyB);
// Wrong — size + contains on a set
assertThat(set).hasSize(2);
assertThat(set).contains("hello", "world");
// Correct
assertThat(set).containsExactlyInAnyOrder("hello", "world");Use containsOnlyKeys when the map must have exactly those keys. Use containsExactlyInAnyOrder for sets (order irrelevant). Use containsExactly when order matters.
Use isTrue() / isFalse() for genuine boolean expressions that are not collection, string, type, reference equality, or membership checks, e.g. filter.keep(path) or method calls that return boolean without a dedicated AssertJ assertion.
Do not use assertThat(x instanceof Foo.class).isTrue() — use assertThat(x).isInstanceOf(Foo.class) instead. For negation, use isNotInstanceOf(...).
Do not use assertThat(a == b).isTrue() for reference equality — use assertThat(a).isSameAs(b) instead.
Do not use assertThat(x == a || x == b).isTrue() for “one of these values” — use assertThat(x).isIn(a, b) instead (or isNotIn(...) for negation).
// Wrong
assertThat(records.get(0).get("dec") instanceof BigDecimal).isTrue();
assertThat(obj instanceof Map).as("Should be a map").isTrue();
assertThat(car.getDoors() == 4 || car.getDoors() == 5).isTrue();
// Correct
assertThat(records.get(0).get("dec")).isInstanceOf(BigDecimal.class);
assertThat(obj).as("Should be a map").isInstanceOf(Map.class);
assertThat(car.getDoors()).isIn(4, 5);// Wrong
assertThat(a.compareTo(b) < 0).isTrue();
assertThat(a.compareTo(b) == 0).isTrue();
// Correct
assertThat(a).isLessThan(b);
assertThat(a).isGreaterThan(b);
assertThat(a).isEqualByComparingTo(b);When the API returns int (not Comparable on the subject), assert on the result:
assertThat(Float16.compare(a, b)).isZero();
assertThat(Float16.compare(a, b)).isPositive();
assertThat(Float16.compare(a, b)).isNegative();For custom Comparator instances comparing values directly:
assertThat(truncated)
.usingComparator(comparator)
.isLessThanOrEqualTo(value);Do not use usingComparator with Float16::compare on boxed Short values — it does not match Float16.compare(short, short) semantics.
The value under test is the AssertJ subject; the known reference is the argument:
// Correct — slice buffer is under test
assertThat(one.array()).as("Should use the same backing array").isSameAs(data.array());
// Correct — dictionary-encoded field should reuse the same object reference
assertThat(car.getModel()).isSameAs(previousCar.getModel());
// Wrong — backing array as subject
assertThat(data.array()).isSameAs(one.array());
// Wrong — reference equality via isTrue()
assertThat(car.model == previousCar.model).isTrue();.as("…") on non-exception assertions is allowed.
// Prefer
assertThat(bytes).containsExactly(1, 2, 3);
assertThat(bytes).hasSize(12);
assertThat(buffer).isEqualTo(expectedArray);
// Byte values from streams — cast to avoid JUnit-style promotion issues
assertThat((int) stream.read()).isEqualTo(i);
assertThat((byte) buffer.get()).isEqualTo((byte) i);Replace custom match helpers with direct AssertJ:
// Wrong
assertMatches(filter, path);
assertDoesNotMatch(filter, path);
// Correct
assertThat(filter.keep(path)).isTrue();
assertThat(filter.keep(path)).isFalse();| Avoid | Use instead |
|---|---|
catchThrowable + assertThat(caught).isInstanceOf / hasMessage* |
assertThatThrownBy(…).isInstanceOf(…).hasMessage* |
assertThatThrownBy without hasMessage |
Add hasMessage / hasMessageContaining from the throw site |
@Rule TemporaryFolder / temp.newFile() |
@TempDir private Path tempDir + tempDir.resolve(...) |
tempDir.toFile().getAbsolutePath() / new File(tempDir.toFile(), …) |
tempDir.resolve(…).toUri() or .toFile() |
new Path(tempDir.toFile().getAbsolutePath()) |
new Path(tempDir.resolve(…).toUri()) |
Files.createFile + Files.delete before CREATE-mode writer |
tempDir.resolve(uniqueName) only — file must not exist |
Duplicate DirectWriterTest in other modules |
extends DirectWriterTest from parquet-hadoop test-jar |
Assume.assumeTrue(...) / Assumptions.assumeTrue(...) |
AssertJ assumeThat(...).isTrue() or fluent assumeThat(value).… |
singleElement() |
containsExactly(element) or explicit checks |
.satisfies(…) |
Direct assertions unless truly necessary |
assertThat(x.toString()) |
assertThat(x).asString() |
assertThat(list.isEmpty()).isTrue() |
assertThat(list).isEmpty() |
assertThat(list.isEmpty()).isFalse() / assertThat(!list.isEmpty()).isTrue() |
assertThat(list).isNotEmpty() |
assertThat(opt.isPresent()).isTrue() |
assertThat(opt).isPresent() |
assertThat(opt.isPresent()).isFalse() / assertThat(opt.isEmpty()).isTrue() |
assertThat(opt).isEmpty() |
assertThat(list.contains(x)).isTrue() |
assertThat(list).contains(x) |
assertThat(list.contains(x)).isFalse() |
assertThat(list).doesNotContain(x) |
assertThat(list).isEqualTo(otherList) |
assertThat(list).containsExactlyElementsOf(otherList) |
assertThat(list.size()).isEqualTo(n) |
assertThat(list).hasSize(n) |
assertThat(list).hasSize(other.size()) / hasSize(array.length) |
assertThat(list).hasSameSizeAs(other) |
assertThat(a.size() < b.size()).isTrue() |
assertThat(a).hasSizeLessThan(b) |
assertThat(array.length).isEqualTo(n) |
assertThat(array).hasSize(n) |
assertThat(it).toIterable() for drained iterators |
assertThat(it).toIterable().containsExactly(1, 2, 3) |
assertThat(it.hasNext()).isFalse() |
assertThat(it).isExhausted() |
assertThat(it.hasNext()).isTrue() |
assertThat(it).hasNext() |
assertThat(list).isEqualTo(stream.collect(toList())) |
assertThat(list).containsExactlyElementsOf(stream.collect(toList())) |
hasSize(n) + containsKey / contains on same map or set |
containsOnlyKeys(…) / containsExactlyInAnyOrder(…) |
assertThat(x instanceof Foo).isTrue() |
assertThat(x).isInstanceOf(Foo.class) |
assertThat(a == b).isTrue() |
assertThat(a).isSameAs(b) |
assertThat(x == a || x == b).isTrue() |
assertThat(x).isIn(a, b) |
assertThat(x).isEqualTo(0) on int/long results |
assertThat(x).isZero() |
assertThat(0 < x).isTrue() |
assertThat(x).isPositive() |
assertThat(file.exists()).isTrue() |
assertThat(file).exists() |
assertThat(true).isTrue() / try-catch for no exception |
assertThatCode(() -> …).doesNotThrowAnyException() |
.as() on assertThatThrownBy |
(omit) |
assertThatThrownBy(() -> { action(); }) (single statement) |
assertThatThrownBy(() -> action()) or method reference |
hasMessage(null) |
(omit hasMessage) |
| Constant as assertion subject | Expression under test as subject |
hasCauseInstanceOf when exception is thrown directly |
Use isInstanceOf on the thrown type |
After writing or changing tests, apply formatting and run tests for the affected module:
./mvnw spotless:apply -pl <module>
mvn -pl <module> test