agentsclimarketplace

Java testing

Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/java-testing

When to activate: Java testing, JUnit 5, Mockito, AssertJ, Testcontainers, WireMock, Spring MVC test, parameterized testsFrom its SKILL.md

Install
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill java-testing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.8 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it

Java Testing Patterns

JUnit 5 Basics

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock UserRepository userRepository;
    @Mock EmailService emailService;
    @InjectMocks UserService userService;

    @Test
    void findById_returnsUser_whenExists() {
        var user = new User(1L, "Alice", "[email protected]");
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        var result = userService.findById(1L);

        assertThat(result).isEqualTo(user.toDto());
        verify(userRepository).findById(1L);
    }

    @Test
    void findById_throwsNotFound_whenMissing() {
        when(userRepository.findById(anyLong())).thenReturn(Optional.empty());

        assertThatThrownBy(() -> userService.findById(99L))
            .isInstanceOf(ResourceNotFoundException.class)
            .hasMessageContaining("99");
    }

    @Nested
    class CreateUser {
        @Test
        void sendsWelcomeEmail_onSuccess() {
            when(userRepository.existsByEmail(any())).thenReturn(false);
            when(userRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));

            userService.create(new CreateUserRequest("Bob", "[email protected]"));

            verify(emailService).sendWelcome(argThat(u -> "[email protected]".equals(u.getEmail())));
        }
    }
}

Parameterized Tests

@ParameterizedTest
@CsvSource({
    "[email protected], true",
    "invalid-email,   false",
    ",                false",
    "missing@domain,  false"
})
void validateEmail(String email, boolean expected) {
    assertThat(EmailValidator.isValid(email)).isEqualTo(expected);
}

@ParameterizedTest
@MethodSource("provideOrders")
void calculateTotal(List<OrderItem> items, BigDecimal expected) {
    assertThat(orderService.calculateTotal(items)).isEqualByComparingTo(expected);
}

static Stream<Arguments> provideOrders() {
    return Stream.of(
        Arguments.of(List.of(item(10, 2), item(5, 3)), new BigDecimal("35")),
        Arguments.of(List.of(), BigDecimal.ZERO)
    );
}

AssertJ Fluent Assertions

// Collections
assertThat(users)
    .hasSize(3)
    .extracting(User::getName)
    .containsExactlyInAnyOrder("Alice", "Bob", "Charlie");

// Exceptions
assertThatThrownBy(() -> service.process(null))
    .isInstanceOf(IllegalArgumentException.class)
    .hasMessage("Input must not be null");

// Soft assertions — all failures reported at once
SoftAssertions.assertSoftly(soft -> {
    soft.assertThat(user.getName()).isEqualTo("Alice");
    soft.assertThat(user.getEmail()).endsWith("@example.com");
    soft.assertThat(user.isActive()).isTrue();
});

Testcontainers

@SpringBootTest
@Testcontainers
class OrderRepositoryTest {

    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
        .withDatabaseName("testdb");

    @DynamicPropertySource
    static void props(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }

    @Autowired OrderRepository repository;

    @Test
    @Transactional
    void savesAndRetrievesOrder() {
        var order = new Order(/* ... */);
        var saved = repository.save(order);
        assertThat(repository.findById(saved.getId())).isPresent();
    }
}

WireMock

@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
class PaymentClientTest {

    @Autowired PaymentClient paymentClient;

    @Test
    void chargeCard_returnsSuccess() {
        stubFor(post(urlEqualTo("/v1/charges"))
            .withRequestBody(matchingJsonPath("$.amount", equalTo("1000")))
            .willReturn(aResponse()
                .withStatus(200)
                .withHeader("Content-Type", "application/json")
                .withBodyFile("charge-success.json")));

        var result = paymentClient.charge(new ChargeRequest("tok_test", 1000));

        assertThat(result.getStatus()).isEqualTo("succeeded");
    }
}

Spring MVC Test

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired MockMvc mvc;
    @MockBean UserService userService;

    @Test
    void getUser_returns200() throws Exception {
        when(userService.findById(1L)).thenReturn(new UserResponse(1L, "Alice"));

        mvc.perform(get("/api/v1/users/1").accept(APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("Alice"));
    }

    @Test
    void createUser_returns201() throws Exception {
        var body = """{"name":"Bob","email":"[email protected]"}""";
        when(userService.create(any())).thenReturn(new UserResponse(2L, "Bob"));

        mvc.perform(post("/api/v1/users")
                .contentType(APPLICATION_JSON)
                .content(body))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.id").value(2));
    }
}

Key Rules

  • @Nested classes group related tests — use them instead of long method name prefixes
  • @ParameterizedTest eliminates copy-paste test methods for boundary conditions
  • Use @MockBean in @WebMvcTest/@SpringBootTest; use @Mock + @ExtendWith(MockitoExtension.class) for pure unit tests
  • Testcontainers static container is reused across test methods in the class — far faster than per-test startup
  • AssertJ extracting() is cleaner than mapping to a list and then asserting — use it for collection element checks

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,758. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.