skip to content

Show how BDDMockito makes a unit test read as Given-When-Then, and explain what belongs in each section.

level: middleimportance: nice to knowfreq 38%

answer

  1. Given = arrange/stub, When = one SUT call, Then = assert + verify
  2. given() matches Given, then().should() matches Then
  3. When needs no Mockito call
  4. Then mixes state asserts and interaction verifies
  5. One action per test

basics

~10 s

Given = set up the mocks with given().willReturn(). When = call the method you're testing. Then = check results with assertions and then(mock).should() verifications. BDDMockito's method names match those three section labels.

solid answer

~40 s

BDDMockito lets a test's code literally mirror the Given-When-Then narrative. The Given block uses given(mock.method()).willReturn(...) to arrange collaborator behavior and any input fixtures. The When block is a single line: the call to the system under test, capturing its result. The Then block holds assertions on that result plus interaction verifications via then(mock).should(). The payoff is that the section comments (// given, // when, // then) match the actual API names, so the test is self-documenting and a reviewer immediately sees the arrange/act/assert phases. The When step needs no Mockito call — it is just exercising real code — which is exactly the clash that classic when() created. Keeping each block focused (arrange only in Given, one action in When, only checks in Then) also encourages tests that assert one behavior at a time.

code

java · 12 lines
java
@Test
void sendsWelcomeEmailOnSignup() {
    // given
    given(userRepo.save(any(User.class))).willAnswer(i -> i.getArgument(0));

    // when
    User created = signupService.register("[email protected]");

    // then
    assertThat(created.email()).isEqualTo("[email protected]"); // state
    then(emailGateway).should().sendWelcome("[email protected]"); // interaction
}

go deeper

for a junior

Can identify which lines are Given, When, and Then and place a stub in Given and a verify in Then.

for a middle

Writes well-structured tests with one action in When and distinguishes state vs interaction assertions in Then.

for a senior

Uses the structure to keep tests focused on one behavior and prefers state assertions over excessive interaction verification.

for a principal

Drives a team testing style where BDD-structured tests read as executable specs, and balances interaction vs state testing to avoid brittle, over-mocked suites.

## The three phases Nearly every good unit test has three phases, also called **Arrange-Act-Assert (AAA)** or, in BDD vocabulary, **Given-When-Then**: 1. **Given (Arrange):** establish the starting world — create inputs and program the fake collaborators (mocks) to respond a certain way. 2. **When (Act):** perform the single action under test — call the method on the *system under test* (SUT), the real object you are testing. 3. **Then (Assert):** check the outcome — assert the returned value and/or verify that the SUT interacted with its collaborators as expected. ## How BDDMockito aligns the code with the phases With classic Mockito the **Given** phase uses a method literally named `when(...)`, which reads as if it were the *When* phase — confusing. BDDMockito renames it to `given(...)`, and renames verification to `then(mock).should()`, so the code matches the narrative: ``` @Test void debitsAccountOnPurchase() { // given given(accountRepo.findById(ID)).willReturn(account); // arrange collaborator var command = new Purchase(ID, money(10)); // arrange input // when Receipt receipt = checkout.process(command); // the single action // then assertThat(receipt.total()).isEqualTo(money(10)); // assert state then(accountRepo).should().save(account); // assert interaction } ``` ## What belongs in each block - **Given:** only setup. All `given(...).willReturn(...)`/`willThrow(...)` stubs, test data, and fixtures. No calls to the SUT. - **When:** exactly **one** call to the SUT, whose result you store. Keeping it to one action keeps the test focused. (For exception tests, the When is the captured throwing call, e.g. via `assertThatThrownBy`.) - **Then:** assertions on the captured result (state-based testing) plus `then(mock).should()` verifications (interaction-based testing). Avoid putting new stubs here. ## State vs interaction assertions The Then block can mix two assertion styles: - **State-based:** check the value the SUT returned (`assertThat(receipt.total())...`). - **Interaction-based:** check that the SUT *called* a collaborator (`then(repo).should().save(...)`). Prefer state assertions where possible and add interaction verification only for behavior that has no observable return value (e.g., a side effect like saving). ## Why it improves tests The naming discipline nudges you to separate arrange/act/assert cleanly, exercise one behavior per test, and write tests that read like an executable specification — the central goal of BDD.

  • Why does the When step usually contain no BDDMockito call at all?
    Because the When is the real action on the system under test — you call actual production code, not a mock. The mocks were arranged in Given and are asserted in Then; the When just exercises the SUT.
  • Should every Then block use then(mock).should()?
    No. Prefer asserting the returned state where you can. Use interaction verification only for side effects that have no observable return value (e.g., saving, sending), to avoid over-specifying implementation details.

It is like a recipe written in standard order: gather ingredients (Given), do the cooking step (When), then taste-test the dish (Then). BDDMockito just labels your code with those same headings.

saying these in an interview costs you the question

  • Putting stubs (given().willReturn()) in the Then block instead of Given.
  • Calling the system under test multiple times in one When, blurring what is being tested.
  • Over-verifying every interaction instead of asserting observable state, leading to brittle tests.

context