Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Jvm Testing

ASecurity

JUnit 5, Mockito, AssertJ, and Testcontainers patterns for any JVM project. Covers test structure, parameterised tests, mocking discipline, fluent assertions, and integration testing with real containers. Stack-agnostic — referenced by every Java plugin in the marketplace. Use this skill to: - Write clear, maintainable unit tests with JUnit 5. - Mock dependencies with Mockito without overusing mocks. - Write expressive assertions with AssertJ. - Spin up real infrastructure (DBs, message brok...

35 stars
0 votes
0 copies
0 views
Added 9/22/2026
testinggojavasqlexpressspringtestingapidatabase

Works with

cliapi

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add AratKruglik/claude-sdlc --skill jvm-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jvm Testing?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Jvm Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aratkruglik-jvm-testing/badge)](https://www.skillsdirectory.com/skills/aratkruglik-jvm-testing)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: jvm-testing
description: |
  JUnit 5, Mockito, AssertJ, and Testcontainers patterns for any JVM project. Covers test structure, parameterised tests, mocking discipline, fluent assertions, and integration testing with real containers. Stack-agnostic — referenced by every Java plugin in the marketplace.

  Use this skill to:
  - Write clear, maintainable unit tests with JUnit 5.
  - Mock dependencies with Mockito without overusing mocks.
  - Write expressive assertions with AssertJ.
  - Spin up real infrastructure (DBs, message brokers) with Testcontainers for integration tests.

  Do NOT use this skill for:
  - Spring-specific test slices (@SpringBootTest, @WebMvcTest, @DataJpaTest — those are in spring-boot-plugin skills).
  - Framework-specific mocking utilities (MockMvc, WebTestClient).
user-invocable: false
paths: ["src/test/**", "**/*Test.java", "**/*Tests.java"]
---

# JVM Testing Patterns (stack-agnostic)

## JUnit 5 fundamentals

```java
import org.junit.jupiter.api.*;
import static org.assertj.core.api.Assertions.*;

class UserServiceTest {

    private UserRepository repository;
    private UserService service;

    @BeforeEach
    void setUp() {
        repository = mock(UserRepository.class);
        service = new UserService(repository);
    }

    @Test
    void registerUser_withValidData_returnsActiveUser() {
        // Arrange
        var command = new RegisterUserCommand("alice@example.com", "Secret1!");
        when(repository.existsByEmail("alice@example.com")).thenReturn(false);
        when(repository.save(any())).thenAnswer(inv -> inv.getArgument(0));

        // Act
        var user = service.register(command);

        // Assert
        assertThat(user.email()).isEqualTo("alice@example.com");
        assertThat(user.isActive()).isTrue();
    }

    @Test
    void registerUser_withDuplicateEmail_throwsException() {
        when(repository.existsByEmail(any())).thenReturn(true);

        assertThatThrownBy(() -> service.register(new RegisterUserCommand("dup@example.com", "pass")))
            .isInstanceOf(DuplicateEmailException.class)
            .hasMessageContaining("dup@example.com");
    }
}
```

**Test method naming:** `methodName_condition_expectedOutcome` (readable without comments). `@DisplayName` for BDD-style prose when the method name would be unwieldy.

**AAA structure:** Arrange → Act → Assert. Separate with blank lines (no comments needed when the structure is clear).

**One assertion concept per test.** Multiple `assertThat` calls are fine when they all verify the same behaviour.

## Parameterised tests

```java
@ParameterizedTest
@ValueSource(strings = { "", " ", "\t", "\n" })
void isBlank_variousBlankStrings_returnsTrue(String input) {
    assertThat(StringUtils.isBlank(input)).isTrue();
}

@ParameterizedTest
@CsvSource({
    "alice@example.com, true",
    "not-an-email,      false",
    "@nodomain.com,     false",
})
void isValidEmail(String email, boolean expected) {
    assertThat(validator.isValid(email)).isEqualTo(expected);
}

@ParameterizedTest
@MethodSource("invalidCommands")
void register_withInvalidCommand_throws(RegisterUserCommand command) {
    assertThatThrownBy(() -> service.register(command))
        .isInstanceOf(ValidationException.class);
}

static Stream<RegisterUserCommand> invalidCommands() {
    return Stream.of(
        new RegisterUserCommand(null, "pass"),
        new RegisterUserCommand("", "pass"),
        new RegisterUserCommand("user@example.com", "")
    );
}
```

## AssertJ — fluent assertions

Prefer AssertJ over JUnit's `assertEquals` — it gives better failure messages and supports fluent chaining.

```java
// Collections
assertThat(users)
    .hasSize(3)
    .extracting(User::email)
    .containsExactlyInAnyOrder("a@x.com", "b@x.com", "c@x.com");

// Exceptions
assertThatThrownBy(() -> service.delete(unknownId))
    .isInstanceOf(EntityNotFoundException.class)
    .hasMessageContaining(unknownId.toString());

// Optional
assertThat(service.findById(42L))
    .isPresent()
    .hasValueSatisfying(u -> assertThat(u.name()).isEqualTo("Alice"));

// Soft assertions — collect all failures
assertSoftly(softly -> {
    softly.assertThat(order.status()).isEqualTo(OrderStatus.CONFIRMED);
    softly.assertThat(order.total()).isEqualByComparingTo("99.99");
    softly.assertThat(order.items()).hasSize(2);
});
```

**Never use `Assertions.assertTrue(a.equals(b))`** — the failure message shows only "expected true" with no values. Use `assertThat(a).isEqualTo(b)`.

## Mockito discipline

```java
// Constructor injection — preferred (no reflection magic, works without Spring)
var repo = mock(UserRepository.class);
var service = new UserService(repo);

// Stubbing — be specific
when(repo.findById(42L)).thenReturn(Optional.of(testUser));

// Argument matchers — use when value doesn't matter; mix carefully
when(repo.existsByEmail(anyString())).thenReturn(false);

// Capture for verification
var captor = ArgumentCaptor.forClass(User.class);
verify(repo).save(captor.capture());
assertThat(captor.getValue().email()).isEqualTo("alice@example.com");

// Verify interaction count
verify(repo, times(1)).save(any());
verify(repo, never()).delete(any());
```

**Avoid `@InjectMocks`** when possible — prefer explicit constructor injection in tests; it makes dependencies visible and avoids field-injection surprises.

**Do not mock value objects or simple data classes.** Only mock boundaries (repositories, HTTP clients, external services).

## Testcontainers — integration tests with real infrastructure

```java
@Testcontainers
class UserRepositoryIT {

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

    @BeforeAll
    static void configure() {
        // Wire datasource — exact mechanism depends on framework
        System.setProperty("spring.datasource.url", postgres.getJdbcUrl());
        System.setProperty("spring.datasource.username", postgres.getUsername());
        System.setProperty("spring.datasource.password", postgres.getPassword());
    }

    @Test
    void saveAndFindById_roundtrip() {
        var repo = buildRepository();
        var user = new User(null, "alice@example.com");

        var saved = repo.save(user);
        var found = repo.findById(saved.id());

        assertThat(found).isPresent()
            .hasValueSatisfying(u -> assertThat(u.email()).isEqualTo("alice@example.com"));
    }
}
```

**Static containers** (`static` field + `@Container`) are reused across all tests in the class — faster than per-test containers. Reuse across test classes via a shared base class or singleton pattern.

**Separate integration tests** from unit tests. Maven Failsafe plugin runs `*IT.java` in `verify`; Gradle can use source sets or a custom test task.

```xml
<!-- Maven: integration tests run in verify phase -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>
```

## Test organisation conventions

```
src/
├── main/java/com/example/...
└── test/java/com/example/
    ├── unit/                   # optional subpackage grouping
    │   └── UserServiceTest.java
    └── integration/
        └── UserRepositoryIT.java
```

Mirror the main package structure — each class under test has a corresponding test class in the same package hierarchy.

**Test class naming:**
- Unit tests: `{Subject}Test`
- Integration tests: `{Subject}IT`
- Slice tests (Spring): `{Subject}Tests` (Spring convention)

## Coverage target

Aim for ≥ 80 % line coverage on business logic (services, domain objects). Framework glue code (configuration, main class) is excluded. Use JaCoCo to measure:

```xml
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>
```

Attribution

AratKruglikAratKruglik
View sourceMore from AratKruglik →
SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Related Skills

Screen Reader Testing

Practical guide to testing web applications with screen readers for comprehensive accessibility validation.

397921 votes

Golang Testing

Go测试模式包括表格驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循TDD方法论,采用地道的Go实践。

2456590 votes

Springboot Tdd

使用JUnit 5、Mockito、MockMvc、Testcontainers和JaCoCo进行Spring Boot的测试驱动开发。适用于添加功能、修复错误或重构时。

2456590 votes

Tdd Workflow

在编写新功能、修复错误或重构代码时使用此技能。强制执行测试驱动开发,包含单元测试、集成测试和端到端测试,覆盖率超过80%。

2456590 votes

Python Testing

使用pytest、TDD方法、夹具、模拟、参数化和覆盖率要求的Python测试策略。

2456590 votes
View all in testing →