- Forward


JUnit v5 (Jupiter)
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Background
Back SMYC Forward
  • Purpose:
    • A way to write, organize, and run repeatable unit tests (i.e., a test harness or testing framework)
  • Why It's Popular:
    • Open source
    • Easy to use
    • Flexible
    • Can be integrated with other tools
Creating Test Classes
Back SMYC Forward
  • Steps:
    • Create a file (usually named ClassNameTest.java)
    • Add the necessary import statements
    • Add a class declaration
    • Add one or more tests (i.e., methods preceded by the annotation @Test)
  • Contents of Tests:
    • Setup code
    • One or more calls to assert___() methods
Some assert___() Methods
Back SMYC Forward
  • Equals Checks:
    • Assertions.assertEquals(expected, actual [, description] )
    • Assertions.assertEquals(expected, actual, tolerance [, description] )
    • Assertions.assertArrayEquals( expected, actual [, tolerance] [,description])
  • True/False Checks:
    • Assertions.assertTrue(actual [, description])
    • Assertions.assertFalse(actual [, description])
Some assert___() Methods (cont.)
Back SMYC Forward
  • Same Reference Checks:
    • Assertions.assertSame(expected, actual [, description] )
  • Null Checks:
    • Assertions.assertNull(actual [, description])
An Example
Back SMYC Forward
  • The Class to Test:
    • Atom
  • The Methods to Test:
    • public int getAtomicNumber()
    • public boolean equals(Atom other)
An Example (cont.)
Back SMYC Forward
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; public class AtomTest { /** * Unit tests for the getAtomicNumber() method */ @Test public void getAtomicNumber_Test() { Atom o; o = new Atom("O", 8, 16); assertEquals(8, o.getAtomicNumber(), "Oxygen"); // Note: // This is a call to Assertions.assertEquals() but the class name // isn't needed because of the static import. } /** * Unit tests for the equals(Atom) method */ @Test public void equals_Test() { Atom h, hh, o; h = new Atom("H", 1, 1); hh = new Atom("H", 1, 1); o = new Atom("O", 8, 16); assertTrue(h.equals(hh), "Two H atoms"); assertFalse(h.equals(o), "H and O"); assertFalse(o.equals(h), "O and H"); } }
Testing Methods that Throw Exceptions
Back SMYC Forward
  • The Most Common Approach:
    • Use the assertThrows() method
  • How?
    • Use a Lambda expression (a representation of a class with a single method)
An Example (cont.)
Back SMYC Forward
  • The Method to Test:
    • The Atom constructor
  • The Expected Result:
    • It should throw an IllegalArgumentException if either of the parameters are negative
  • Implications for the Test Method:
    • It should not have any assert___() invocations after the exception will be thrown
An Example (cont.)
Back SMYC Forward
/** * Test that the constructor validates properly. */ @Test public void constructor_IllegalArguments() throws IllegalArgumentException { assertThrows(IllegalArgumentException.class, () -> {new Atom("O", -8, -16);}); }
An Easier Approach for Beginning Programmers
Back SMYC Forward
/** * Test that the constructor validates properly. */ @Test public void constructor_IllegalArguments() { try { new Atom("O", -8, -16); // Shouldn't get here fail("Constructor should have thrown an IllegalArgumentException"); } catch (IllegalArgumentException iae) { // The exception was thrown as expected } }
Common Setup/Cleanup
Back SMYC Forward
  • The Situation:
    • All of the test methods use the same setup code and/or the same cleanup code
  • One Approach:
    • Move the code to private methods and invoke them at the top and/or bottom of each test method
  • A More Elegant Approach:
    • Use the @BeforeEach annotation to indicate that the method should be invoked before every test method and the @AfterEach annotation to indicate that the method should be invoked after every test method
Common Setup/Cleanup (cont.)
Back SMYC Forward
  • Remember:
    • You must import org.junit.jupiter.api.BeforeEach and/or org.junit.jupiter.api.AfterEach
    • Methods annotated with @BeforeEach or @AfterEach will be invoked before/after every test method
  • Note:
    • In general, you should not count on the test methods being executed in a particular order
Some Notes About Terminology
Back SMYC Forward
  • "Assertions":
    • The assert___() methods are often called assertions, but they should not be confused with assert statements in Java
  • Test (and "Test Case"):
    • JUnit calls each test method an individual test but each invocation of an assert___() method can be thought of as an individual test
Executing JUnit Tests
Back SMYC Forward
  • The Basics:
    • You must execute a "test runner" that executes all of the appropriately annotated methods in a test class
  • From the Command Line:
    • You have to include the appropriate .jar files in the CLASSPATH and execute a "test runner" (commonly org.junit.platform.console.ConsoleLauncher) passing it the name of the test class
  • From an IDE:
    • You have to let the IDE know that the test class is a JUnit test (usually when you create it) and then, when you run it, the IDE knows to actually start a "test runner"
There's Always More to Learn
Back -