Appearance
Assumptions
Chapter 5's assertions decide whether a test passes or fails. An assumption decides something else: whether a test should run at all, given the conditions it finds.
The need
Some tests should run only under a condition: a certain environment, a certain Java version. When the condition does not hold, the test should be skipped, not failed.
Why not a plain if?
java
@Test
void someTest() {
if (a > b) {
// test logic
}
}When the condition is false, the method simply returns, and the test is reported as passed, which is misleading: nothing was tested. We want it marked skipped (aborted): with ten tests and one condition false, nine run and one shows as skipped, none as failed.
Assumptions
The Assumptions class provides static methods (each with overloads, including one with a message):
java
assumeTrue(boolean condition)
assumeTrue(boolean condition, String message)
assumeFalse(boolean condition)
assumeFalse(boolean condition, String message)
assumingThat(boolean condition, Executable executable)If the assumption does not hold, the test is aborted (skipped).
assumeTrue: skip if the condition is false
java
public class AssumptionTest {
@BeforeEach
void setup() {
System.setProperty("env", "Prod");
}
@Test
void testForDevelop() {
Assumptions.assumeTrue("Dev".equals(System.getProperty("env")),
"Test case is not eligible for this env");
// test logic for Dev
}
@Test
void testForProduction() {
Assumptions.assumeTrue("Prod".equals(System.getProperty("env")));
System.out.println("Test case can proceed");
}
}text
testForProduction() ✔ passed (prints "Test case can proceed")
testForDevelop() ↷ aborted Assumption failed: Test case is not eligible for this envHow it works. It is an if after all, with a twist: when the condition is false, it throws TestAbortedException (from org.opentest4j). The engine reports a test that ends with that exception as aborted, not failed. You could throw it yourself instead of using Assumptions:
java
throw new TestAbortedException("skipped by hand"); // reported as abortedassumeFalse: run only if the condition is false
java
@Test
void testWithOldJavaVersion() {
Assumptions.assumeFalse(Runtime.version().feature() == 21,
"Test case is not eligible for this java version");
// test logic
}On Java 21 the condition is true, so the test is skipped with that message; on any other version it runs.
assumingThat: a conditional block
java
@Test
void testAssumingThat() {
Assumptions.assumingThat(
Runtime.version().feature() == 21,
() -> System.out.println("This code block runs only if condition is true")
);
System.out.println("This code will run always");
}The block (an Executable, so a lambda) runs only if the condition is true. Unlike the other two, a false condition does not skip the test: the block is skipped and the rest of the test still runs.
An assumption can also go in @BeforeAll: if it fails there, every test in the class is aborted.
Next: Assumptions decide from inside a test whether it runs. Chapter 11 decides from the outside which tests run: tagging tests and filtering by tag.
Check yourself
- Why is a plain
ifaround the test logic not good enough? - What is the difference between a failed and an aborted (skipped) test?
- What does
assumeTruedo internally when the condition is false? - When does a test using
assumeFalse(x)run? - With
assumingThat(false, block), is the test skipped? What runs? - How can you skip a test without the
Assumptionsclass?
Answers
- When the condition is false the method just returns and the test is reported as passed, though nothing was tested.
- A failed test found a problem; an aborted test was not run because its preconditions did not hold, and is shown as skipped.
- It throws
TestAbortedException, which the engine reports as aborted. - Only when
xis false. - No: only the block is skipped; the rest of the test runs.
- Throw
TestAbortedExceptionyourself.