Testing
The JVM testing toolchain: JUnit 5 for writing and running tests, Mockito for isolating collaborators, AssertJ and Hamcrest for expressive assertions, and JaCoCo for coverage. Interviewers expect fluency with these because they are what you would use on day one.
part ofJavaoverview, primer and where to startread it →on this pageshowhide
explore
- JUnit (Unit Testing)64 questions
- JUnit 4 vs JUnit 55 questions
- @Test5 questions
- @BeforeEach / @AfterEach5 questions
- @BeforeAll / @AfterAll5 questions
- JUnit Assertions6 questions
- assertThrows5 questions
- assertAll4 questions
- @ParameterizedTest6 questions
- @DisplayName5 questions
- @Disabled5 questions
- @Nested4 questions
- Assumptions4 questions
- Test Lifecycle (per-method vs per-class)5 questions
- Mockito (Mocking)47 questions
- Mockito Mock Creation5 questions
- Stubbing (when/thenReturn)5 questions
- Stubbing Exceptions (thenThrow)4 questions
- Verification (verify)5 questions
- Argument Matchers5 questions
- ArgumentCaptor5 questions
- Spy vs Mock4 questions
- @Mock / @InjectMocks5 questions
- Mocking Static Methods5 questions
- BDDMockito (given/willReturn)4 questions
- Assertion Libraries (AssertJ / Hamcrest)11 questions
- AssertJ6 questions
- Hamcrest Matchers5 questions
- JaCoCo Coverage5 questions
questions
132 · 5 sectionsTesting Methodology (see Testing & Quality Disciplines)
all 5 Testing Methodology (see Testing & Quality Disciplines) questions →How do you write a basic unit test in JUnit 5, and what do the core annotations (@Test, @BeforeEach, @AfterEach, @BeforeAll, @AfterAll) do?
basics
~10 sA unit test is a method marked @Test that checks one behavior using assertions like assertEquals. @BeforeEach/@AfterEach run setup/cleanup before and after every test; @BeforeAll/@AfterAll run once for the whole class.
Using Mockito, how do test doubles map to stubbing (when/thenReturn) versus verification (verify), and how does this relate to the dummy/fake/stub/spy/mock taxonomy?
basics
~20 sMockito creates fake versions of dependencies. when(x).thenReturn(y) sets up canned answers (stubbing — controlling input). verify(x).method() checks that your code actually called a dependency (verification — checking interactions). Stubs feed data in; mocks confirm behavior.
Compare assertion styles in Java tests: built-in JUnit assertions vs AssertJ vs Hamcrest. When would you choose each?
basics
~10 sJUnit's assertEquals is fine for simple checks. AssertJ gives fluent, chainable assertions like assertThat(list).contains(x) with great readability and IDE autocomplete. Hamcrest uses matcher objects like assertThat(x, is(5)). AssertJ is the modern default.
How do you practice red-green-refactor TDD in Java with JUnit 5, and how do parameterized tests (@ParameterizedTest) support data-driven test design?
basics
~20 sTDD: write a failing test first (red), write just enough code to pass (green), then clean up the code (refactor), repeating in small loops. JUnit's @ParameterizedTest runs the same test logic over many input sets (via @ValueSource, @CsvSource, @MethodSource) instead of copy-pasting tests.
How does the testing pyramid map onto a typical Java/Spring stack, and what causes flaky tests in this context?
basics
~20 sThe pyramid says: many fast unit tests (plain JUnit + Mockito), fewer integration tests (@SpringBootTest, Testcontainers), and very few slow end-to-end tests. Flaky tests pass and fail without code changes, often due to timing, shared state, real time/randomness, or test ordering.
What is JUnit 5's assertAll, and what problem does it solve compared to writing several separate assertions?
basics
~20 sassertAll runs a group of assertions together and reports every failure at once. With plain asserts, the test stops at the first failure, so you only see one problem. assertAll shows all of them in one run.
In JUnit 5's assertEquals, what is the argument order, and why does getting it wrong matter?
basics
~20 sThe order is assertEquals(expected, actual). The first value is what you expect, the second is what your code produced. Swapping them still passes or fails correctly, but the failure message reads backwards and confuses you.
What is JUnit 5's assertThrows and how do you use it to verify that code throws an expected exception?
basics
~20 sassertThrows runs a piece of code and checks it throws the exception type you expect. You pass the expected exception class and a lambda holding the code. The test passes only if that code throws that type (or a subtype).
In JUnit 5, what is the difference between an assumption (assumeTrue) and an assertion (assertTrue)? What happens to a test when each one fails?
basics
~20 sAn assertion checks the result you are testing: if it is false, the test FAILS. An assumption checks a precondition: if it is false, the test is SKIPPED (aborted), not failed. So a failed assumption is treated like a test that did not run.
What do @BeforeAll and @AfterAll do in JUnit 5, and how do they differ from @BeforeEach and @AfterEach?
basics
~10 s@BeforeAll runs once before all the tests in a class; @AfterAll runs once after all of them. @BeforeEach and @AfterEach run before and after every single test method instead.
What is Mockito's ArgumentCaptor and what problem does it solve?
basics
~10 sArgumentCaptor catches the actual value passed to a mock's method so you can store it and check it afterward with normal assertions, instead of only checking that the method was called.
What are argument matchers in Mockito, and why would you use any() or eq() instead of passing a literal value when stubbing or verifying?
basics
~20 sArgument matchers like any() or eq() tell Mockito how to match the arguments of a call instead of comparing exact values. Use any() when the value doesn't matter and eq(x) when you need a specific value but other arguments use matchers.
What do the Mockito @Mock and @InjectMocks annotations do, and how do they work together in a unit test?
basics
~10 s@Mock creates a fake stand-in for a dependency. @InjectMocks creates the real object you are testing and pushes those mocks into it, so you can test it in isolation without its real collaborators.
What does a freshly created, unstubbed Mockito mock return when its methods are called, for various return types?
basics
~20 sAn unstubbed mock returns safe empty defaults: null for objects, 0 for numbers, false for booleans, and empty collections (an empty list/set/map, not null). So calling a method you didn't stub won't throw on its own.
What is a mock object in Mockito, how do you create one, and why would you use it in a unit test?
basics
~20 sA mock is a fake stand-in for a real object that you create with Mockito.mock(SomeClass.class). You use it to replace a real collaborator so your test exercises only the one class you care about, without its dependencies doing real work.
What is AssertJ and how does its fluent assertThat(...) style differ from JUnit's assertEquals or Hamcrest's assertThat?
basics
~20 sAssertJ is a Java assertion library. You write assertThat(actual) then chain readable checks like .isEqualTo(expected) or .isNotNull(). It reads left-to-right (actual first) and gives clear failure messages, unlike assertEquals(expected, actual) where the argument order is easy to mix up.
What is Hamcrest, and how does the assertThat(actual, matcher) style of assertion differ from a classic assertEquals(expected, actual)?
basics
~10 sHamcrest is a library of reusable 'matcher' objects. Instead of assertEquals(2, x), you write assertThat(x, is(2)). The matcher describes what you expect, reads almost like English, and prints a clear message when it fails.
How do you assert on collections and iterables with AssertJ (contains, containsExactly, containsExactlyInAnyOrder, hasSize, extracting)?
basics
~20 sCall assertThat on the collection, then chain: hasSize(n) for count, contains(a, b) to check elements are present, containsExactly(...) for the exact contents in order, containsExactlyInAnyOrder(...) ignoring order, and extracting("field") to assert on one property of each element.
How do you assert that code throws an exception in AssertJ using assertThatThrownBy and assertThatExceptionOfType?
basics
~10 sWrap the failing call in a lambda: assertThatThrownBy(() -> service.run()).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("bad"). It runs the lambda, catches the thrown exception, and lets you assert on its type and message. assertThatExceptionOfType(X.class).isThrownBy(() -> ...) is an equivalent style.
Walk through the common Hamcrest core matchers (is, equalTo, not, nullValue, containsString, hasItem) — what does each check and how do you read them?
basics
~10 sequalTo checks equality, is wraps a matcher to read nicer, not inverts, nullValue checks for null, containsString checks a substring, and hasItem checks a collection contains an element. You combine them like assertThat(list, hasItem(equalTo(3))).
What is JaCoCo, and how does it measure code coverage on the JVM?
basics
~20 sJaCoCo is a Java tool that measures how much of your code your tests actually run. While the tests execute, it watches the compiled code and records which lines and branches were hit, then produces a report.
Explain JaCoCo's coverage metrics — instruction, line, branch, method, and complexity — and why line coverage alone can be misleading.
basics
~20 sJaCoCo counts coverage in several ways: how many lines ran, how many of the true/false paths of if/switch ran (branches), how many low-level instructions and methods ran, and code complexity. Line coverage can hide untested branches — a line can run yet only one side of its condition is checked.
How do you wire JaCoCo into a Gradle or Maven build to generate a coverage report?
basics
~20 sAdd the JaCoCo plugin to your build. It attaches an agent to the test run so coverage is recorded, then a report task turns that data into an HTML report. In Gradle you apply the jacoco plugin and run jacocoTestReport; in Maven you bind the prepare-agent and report goals.
How do you enforce a minimum coverage threshold in the build so a drop fails CI, and how do you exclude code that shouldn't count?
basics
~20 sJaCoCo has a verification step that fails the build if coverage falls below a number you set. In Gradle it's jacocoTestCoverageVerification; in Maven it's the check goal with rules. You can also exclude generated or boilerplate code (DTOs, generated sources) so it doesn't drag the number down.
What are the limits of code coverage as a quality signal, and how should an org set coverage policy without encouraging gaming?
basics
~20 sCoverage shows which code ran during tests, not whether the tests check the right things. You can hit 100% with tests that assert nothing. So set realistic targets, focus on new/changed code, and pair coverage with techniques like mutation testing rather than chasing a single big percentage.