The document provides an overview of useful assertions, assumptions, annotations, and code snippets for testing with JUnit, including how to write parameter resolvers to extend tests, use annotations like @Test and @BeforeEach for marking test methods and lifecycle hooks, and leverage features like nested tests, dynamic tests, and contract testing with interfaces.
The document provides an overview of useful assertions, assumptions, annotations, and code snippets for testing with JUnit, including how to write parameter resolvers to extend tests, use annotations like @Test and @BeforeEach for marking test methods and lifecycle hooks, and leverage features like nested tests, dynamic tests, and contract testing with interfaces.
Assertions and assumptions Parameter resolution Useful annotations
Use assertions to verify the behavior under test: ParameterResolver - extension interface to provide parameters @Test - marks a test method Assertions.assertEquals(Object expected, @TestFactory - method to create test cases Object actual, Supplier<String> message) public class MyInfoResolver implements ParameterResolver { at Runtime public Object resolve(ParameterContext paramCtx, @DisplayName - make reports readable with // Group assertions are run all together and ExtensionContext extCtx) { return new MyInfo(); proper test names reported together. Assertions.assertAll(“heading”, } @BeforeAll/@BeforeEach - lifecycle methods () -> assertTrue(true), } executed prior testing () -> assertEquals(“expected”, @AfterAll/AfterEach - lifecycle methods for cleanup objectUnderTest.getSomething()); Extend your tests with your parameter resolver. @Tag - declare tags to separate tests into suites @ExtendWith(MyInfoResolver.class) @Disabled - make JUnit skip this test. // To check for an exception: class MyInfoTest { … } expectThrows(NullPointerException.class, Use @Nested on an inner class to control the () -> { ((Object) null).getClass();}); Useful code snippets order of tests.
@TestFactory Use @ExtendWith() to enhance the execution:
Stream<DynamicTest> dynamicTests(MyContext ctx) { provide mock parameter resolvers and specify // Generates tests for every line in the file conditional execution. return Files.lines(ctx.testDataFilePath).map(l -> dynamicTest(“Test:” + l, () -> assertTrue(runTest(l))); Use the lifecycle and @Test annotations on the } default methods in interfaces to define contracts: @ExtendWith({ MockitoExtension.class, DataParameterProvider.class }) @Test class Tests { interface HashCodeContract<T> { ArrayList<String> list; <T> getValue(); <T> getAnotherValue(); @BeforeEach @Test void init() { /* init code */ } void hashCodeConsistent() { assertEquals(getValue().hashCode(), @Test getAnotherValue().hashCode(), @DisplayName(“Add elements to ArrayList”) “Hashes differ”); void addAllToEmpty(Data dep) { } @Nested list.addAll(dep.getAll()); Test class assertAll(“sizes”, () -> assertEqual(dep.size(), list.size(), "Never trust a test you () -> “Unexpected size:” + instance), () -> assertEqual(dep.getFirst(), list.get(0), haven't seen fail." () -> “Wrong first element” + instance)); — Colin Vipurs } }