unit-test-service-layer — Claude Code skill: Mockito service tests
A skill that gives the agent a Mockito pattern for service-layer unit tests: mock repositories, verify calls, cover exception paths.
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a claude-codeWhat unit-test-service-layer does
The skill walks through testing @Service classes: enable Mockito annotations with @ExtendWith(MockitoExtension.class), declare dependencies as @Mock and the service under test as @InjectMocks. Then Arrange-Act-Assert — set up data and stub returns with when().thenReturn(), call the method, assert the result with AssertJ and check interactions with verify(). Each step has a validation checkpoint: run the test, confirm the green bar.
Exception paths get their own section. The mock is configured with when().thenThrow(), and the test asserts the exception type and message. At the end the workflow runs the full suite (mvn test or gradle test) and a coverage report via mvn test jacoco:report. A references/examples.md file inside the skill covers more ground: multiple dependencies, argument captors, async services, InOrder verification.
The constraints matter more than the examples. Value objects and DTOs are never mocked — you build real instances with test data. Argument matchers like any() and eq() can't be mixed with actual values in the same stub, or the stub won't match. Private methods are tested through public behaviour only. And if a service needs too many mocks to test, that's a signal to refactor rather than pile more collaborators into the test.
What it helps with
- write a service unit test without booting a Spring context or a database
- mock a repository and check the service called it with the right argument
- assert that a method throws the expected exception on an empty result
- stub an external client response so the test never hits the network
- split a test into Arrange-Act-Assert and remember to verify interactions
Example prompts for the agent
- Write Mockito unit tests for
UserService: mockUserRepository, cover the found-user path and theUserNotFoundExceptioncase. - Add a test that verifies
emailService.sendWelcomeEmailis called when a new user registers. - Run
mvn testand show me which service methods still have no coverage.
How to install unit-test-service-layer
1Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a claude-code2Manually: put the files in place
~/.claude/skills/unit-test-service-layer/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/unit-test-service-layer/
1Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a codex2Manually: put the files in place
.agents/skills/unit-test-service-layer/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a cursor2Manually: put the files in place
.cursor/skills/unit-test-service-layer/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install giuseppe-trisciuoglio/developer-kit unit-test-service-layer2Manually: put the files in place
.github/skills/unit-test-service-layer/SKILL.md1Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a gemini-cli2Platform CLI
gemini skills install https://github.com/giuseppe-trisciuoglio/developer-kit --path plugins/developer-kit-java/skills/unit-test-service-layerManually: put the files in place
.devin/skills/unit-test-service-layer/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about unit-test-service-layer
How do I install unit-test-service-layer in Claude?
Run npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-service-layer -a claude-code. The skill lands in ~/.claude/skills/unit-test-service-layer/SKILL.md.
What does unit-test-service-layer do?
It hands the agent Mockito patterns for service-layer unit tests: mocked repositories and clients, verified invocations, exception scenarios. Tests run without a Spring container or database.
How is this different from integration tests?
It targets isolated business-logic tests. Dependencies are replaced with mocks, so no database or external API is involved in the run.
Source text
SKILL.md · MIT
---
name: unit-test-service-layer
description: Provides patterns for unit testing service layer with Mockito. Creates isolated tests that mock repository calls, verify method invocations, test exception scenarios, and stub external API responses. Use when testing service behaviors and business logic without database or external services.
allowed-tools: Read, Write, Bash, Glob, Grep
---
# Unit Testing Service Layer with Mockito
## Overview
Provides patterns for unit testing `@Service` classes using Mockito. Mocks repository calls, verifies method invocations, tests exception scenarios, and stubs external API responses. Enables fast, isolated tests without Spring container or database.
## When to Use
- Testing business logic in `@Service` classes
- Mocking repository and external client dependencies
- Verifying service interactions with mocked collaborators
- Testing error handling and edge cases in services
- Writing fast, isolated unit tests (no database, no API calls)
## Instructions
Follow this workflow to test service layer with Mockito, including validation checkpoints:
### 1. Setup Test Class
Use `@ExtendWith(MockitoExtension.class)` to enable Mockito annotations.
### 2. Declare Mocks with `@Mock` and `@InjectMocks`
Use `@Mock` for dependencies (repositories, clients) and `@InjectMocks` for the service under test.
### 3. Arrange-Act-Assert with Validation
**Arrange**: Create test data and configure mock return values using `when().thenReturn()`.
**Act**: Execute the service method being tested.
**Assert**:
- Verify returned values with AssertJ assertions
- Verify mock interactions with `verify()`
- **Validation checkpoint**: Run test and confirm green bar
### 4. Test Exception Scenarios
Configure mocks to throw exceptions with `when().thenThrow()`.
**Validation checkpoint**: Verify exception type and message
### 5. Verify Complete Coverage
- Run full test suite: `mvn test` or `gradle test`
- Check coverage report: `mvn test jacoco:report`
- **Validation checkpoint**: Confirm all service methods have corresponding tests
## Examples
### Basic Service Test Pattern
```java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldReturnUserWhenFound() {
// Arrange
User expected = new User(1L, "Alice");
when(userRepository.findById(1L)).thenReturn(Optional.of(expected));
// Act
User result = userService.getUser(1L);
// Assert
assertThat(result.getName()).isEqualTo("Alice");
verify(userRepository).findById(1L);
}
@Test
void shouldThrowWhenUserNotFound() {
// Arrange
when(userRepository.findById(999L)).thenReturn(Optional.empty());
// Act & Assert
assertThatThrownBy(() -> userService.getUser(999L))
.isInstanceOf(UserNotFoundException.class);
}
}
```
### Verify Method Invocations
```java
@Test
void shouldSendEmailOnUserCreation() {
User newUser = new User(1L, "Alice", "[email protected]");
when(userRepository.save(any(User.class))).thenReturn(newUser);
enrichmentService.registerNewUser("Alice", "[email protected]");
verify(userRepository).save(any(User.class));
verify(emailService).sendWelcomeEmail("[email protected]");
}
```
For additional patterns (multiple dependencies, argument captors, async services, InOrder verification), see `references/examples.md`.
## Best Practices
- **Use `@ExtendWith(MockitoExtension.class)`** for JUnit 5 integration
- **Mock only direct dependencies** of the service under test
- **Verify interactions** to ensure correct collaboration
- **Test one behavior per test method** - keep tests focused
- **Use descriptive variable names**: `expectedUser`, `actualUser`, `captor`
- **Create real instances** for value objects and DTOs (don't mock them)
## Constraints and Warnings
- Do not mock value objects or DTOs; create real instances with test data.
- Avoid mocking too many dependencies; consider refactoring if a service has too many collaborators.
- Tests must be independent; do not rely on execution order.
- Be cautious with `@Spy`; partial mocking is harder to understand and maintain.
- Do not test private methods directly; test them through public method behavior.
- Argument matchers (`any()`, `eq()`) cannot be mixed with actual values in the same stub.
- Avoid over-verifying; verify only interactions important to the test scenario.
## References
- [Mockito Documentation](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html)
- [JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/)
- [AssertJ Assertions](https://assertj.github.io/assertj-core-features-highlight.html)
© giuseppe-trisciuoglio · MIT · giuseppe-trisciuoglio/developer-kit