Claude Skills Guide

Claude Code Mockito Java Testing Workflow

Java developers working with Mockito often spend significant time writing test doubles, configuring stubs, and verifying interactions. Claude Code accelerates this workflow by generating boilerplate, suggesting edge cases, and helping structure tests that follow best practices. This guide shows practical approaches for combining Claude Code with your Mockito-based testing.

Setting Up Mockito with Claude Code

When working on a Java project with Mockito, start by ensuring your dependencies are correctly configured. Claude Code can verify your pom.xml or build.gradle includes the right testing dependencies.

<!-- Maven dependencies for Mockito -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.8.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>5.8.0</version>
    <scope>test</scope>
</dependency>

If you’re using JUnit 5, include the Mockito extension to enable cleaner test class initialization:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
    // Your test methods here
}

Generating Test Classes with Claude Code

Claude Code excels at generating test classes quickly. When you need a new test for a service class, provide the source class and request a complete test file. For example, if you have an OrderService that depends on PaymentGateway, ask Claude to create a test that mocks the dependency:

“Create a JUnit 5 test class for OrderService that mocks PaymentGateway using Mockito. Include tests for successful order placement, payment failure handling, and inventory validation.”

Claude generates something like this:

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock
    private PaymentGateway paymentGateway;

    @Mock
    private InventoryService inventoryService;

    @InjectMocks
    private OrderService orderService;

    @Test
    void shouldPlaceOrderSuccessfully() {
        // Arrange
        Order order = Order.builder()
            .id("ORD-001")
            .amount(new BigDecimal("99.99"))
            .build();
        
        when(paymentGateway.process(any()))
            .thenReturn(PaymentResult.success());
        when(inventoryService.checkAvailability(any()))
            .thenReturn(Availability.available());

        // Act
        OrderResult result = orderService.placeOrder(order);

        // Assert
        assertTrue(result.isSuccess());
        verify(paymentGateway).process(any());
    }

    @Test
    void shouldFailWhenPaymentDeclined() {
        // Arrange
        Order order = Order.builder()
            .id("ORD-002")
            .amount(new BigDecimal("199.99"))
            .build();
        
        when(paymentGateway.process(any()))
            .thenReturn(PaymentResult.declined("Insufficient funds"));

        // Act
        OrderResult result = orderService.placeOrder(order);

        // Assert
        assertFalse(result.isSuccess());
        assertEquals("PAYMENT_DECLINED", result.getErrorCode());
    }
}

Working with Argument Matchers

Mockito’s argument matchers can be tricky. Claude Code helps construct proper matchers and avoids common pitfalls like using matchers outside of verification or stubbing:

// Proper use of ArgumentMatchers
when(userRepository.findById(anyLong())).thenReturn(Optional.of(user));
when(orderRepository.save(argThat(order -> order.getStatus().equals("PENDING"))))
    .thenReturn(savedOrder);

// Verification with matchers
verify(repository, times(1)).deleteById(eq(1L));
verify(repository, never()).deleteById(anyLong());

Testing Private Methods and Legacy Code

When testing legacy code or private methods, you have several strategies. Claude Code can recommend the best approach based on your situation:

  1. Test the public API — Most private methods have public entry points worth testing
  2. Use reflection for unit tests — For truly isolated private method testing:
@Test
void shouldCalculateDiscountForPrivateMethod() throws Exception {
    PricingService service = new PricingService();
    
    Method calculateDiscount = PricingService.class
        .getDeclaredMethod("calculateDiscount", BigDecimal.class, CustomerType.class);
    calculateDiscount.setAccessible(true);
    
    BigDecimal discount = (BigDecimal) calculateDiscount
        .invoke(service, new BigDecimal("100"), CustomerType.PREMIUM);
    
    assertEquals(new BigDecimal("20"), discount);
}
  1. Extract to package-private methods — Refactoring makes testing easier without compromising encapsulation

Using the TDD Skill for Test-First Development

Activate the built-in tdd skill to guide Claude toward test-first development:

/tdd

This skill instructs Claude to write failing tests before implementing functionality. When working with Mockito, this means:

  1. Describe the behavior you want
  2. Let Claude write the test with appropriate mocks
  3. Run the test to see it fail
  4. Implement the code to make tests pass
  5. Refactor while keeping tests green

Managing Test Data with Fixtures

Create reusable test fixtures to keep tests clean:

class TestFixtures {
    
    static Customer standardCustomer() {
        return Customer.builder()
            .id(1L)
            .name("Test Customer")
            .email("test@example.com")
            .type(CustomerType.STANDARD)
            .build();
    }
    
    static Customer premiumCustomer() {
        return Customer.builder()
            .id(2L)
            .name("Premium Customer")
            .email("premium@example.com")
            .type(CustomerType.PREMIUM)
            .build();
    }
    
    static Order completedOrder(Customer customer) {
        return Order.builder()
            .id("ORD-COMPLETE")
            .customer(customer)
            .status(OrderStatus.COMPLETED)
            .total(new BigDecimal("250.00"))
            .build();
    }
}

Reference these in your tests:

@Test
void shouldApplyDiscountForPremiumCustomers() {
    Customer premium = TestFixtures.premiumCustomer();
    Order order = TestFixtures.completedOrder(premium);
    
    BigDecimal finalPrice = pricingService.calculateFinalPrice(order);
    
    assertTrue(finalPrice.compareTo(order.getTotal()) < 0);
}

Integrating with CI/CD Pipelines

Run your Mockito tests as part of your continuous integration:

# Run only tests (no build)
mvn test

# Run specific test class
mvn test -Dtest=OrderServiceTest

# Run with coverage
mvn test -Dcoverage=true

Claude Code can help set up GitHub Actions workflows that run your test suite on every pull request, ensuring mock-based tests continue to pass as your codebase evolves.

Common Mockito Patterns

Several patterns appear frequently in Mockito-based testing:

Verifying interactions:

// Verify method was called
verify(mock).someMethod();

// Verify exact number of calls
verify(mock, times(2)).someMethod();

// Verify no interactions
verifyNoInteractions(mock);

Spying on real objects:

List<String> list = new ArrayList<>();
List<String> spy = spy(list);

when(spy.size()).thenReturn(5); // Stub specific method
doReturn("item").when(spy).get(0); // For void methods

assertEquals(5, spy.size());

Answer callbacks:

when(mock.getData(anyString())).thenAnswer(invocation -> {
    String arg = invocation.getArgument(0);
    return "Processed: " + arg;
});

Leveraging Claude Skills for Testing

Beyond the tdd skill, several other skills enhance Java testing workflows:

Configure these skills in your project’s CLAUDE.md to establish consistent testing practices.

Debugging Mock Behavior

When tests fail unexpectedly, check your mock configuration:

// Use DebugTestRule or inline verification
@Test
void debugMockInteractions() {
    // Your test code
    
    // Add after test runs
    verifyNoMoreInteractions(mock);
}

Enable Mockito logging to see what’s happening:

# Logitech configuration
org.mockito.MockitoDebugger=DEBUG

Summary

Claude Code transforms your Mockito testing workflow by generating boilerplate, suggesting edge cases, and helping structure maintainable tests. Focus on writing clear tests that verify behavior rather than implementation details. Use the tdd skill for test-first development, create reusable fixtures to reduce duplication, and integrate testing into your CI pipeline for consistent confidence in your codebase.

Built by theluckystrike — More at zovo.one