Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict).

MITAuto-check: notesBackend & APIs

Install Unit Test Caching

skills CLI
$ npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-caching -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install giuseppe-trisciuoglio/developer-kit unit-test-caching --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/giuseppe-trisciuoglio/developer-kit.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/developer-kit-java/skills/unit-test-caching .claude/skills/unit-test-caching && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
unit-test-caching
GitHub stars
357
Token cost
~2.9k tokens
SKILL.md length
392 words
Files
1
Skills in repo
115
Repo updated
First seen
Licence
MIT

At a glance

Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict).

  • Works in 8 steps: Configure in-memory CacheManager: Use… → Set up test fixtures: Mock repository… → Verify repository call counts: Use… → …
  • Tasks that involve Caching
  • SKILL.md covers Overview, When to Use, Instructions and Examples, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Unit Test Caching is an agent skill from giuseppe-trisciuoglio/developer-kit. Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict). Generates test code that mocks cache managers, verifies cache hit/miss behavior, tests cache key generation with SpEL expressions, validates eviction strategies, and checks conditional caching scenarios. Triggers: caching tests, test Spring cache, mock cache, Spring Boot caching, cache hit/miss verification, @Cacheable testing.

Its SKILL.md is about 2.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Caching, Unit testing and Backend development. It works with Spring Boot. The repository describes itself as: Modular plugin marketplace for Claude Code and agentic CLIs, with validated, spec-driven skills, agents, commands, and workflows for Java, TypeScript, Python, PHP, AWS, and AI. The licence is MIT.

When your agent uses it

  • Tasks that involve Caching
  • Tasks that involve Unit testing
  • Tasks that involve Backend development

Example prompts

  • “Use the unit-test-caching skill to provide patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict)”
  • “/unit-test-caching”

Requirements

  • Pre-approved tools (allowed-tools): Read, Write, Bash, Glob, Grep

Workflow steps

8 steps, taken from the first numbered list in SKILL.md.

  1. Configure in-memory CacheManager: Use ConcurrentMapCacheManager for tests
  2. Set up test fixtures: Mock repository and create service instance in @BeforeEach
  3. Verify repository call counts: Use times(n) assertions to confirm cache behavior
  4. Test cache hit: Call method twice, verify repository called once
  5. Test cache miss: Verify repository called on each invocation
  6. Test eviction: After @CacheEvict, verify repository called again on next read
  7. Test key generation: Verify compound keys from SpEL expressions
  8. Validate conditional caching: Test unless (null results) and condition (parameter-based)

What it can do on your machine

Read from SKILL.md and the folder at commit fe73fb3. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Write
    • Bash
    • Glob
    • Grep

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are java, xml and kotlin).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • docs.spring.io

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Unit Test Caching loads about 2.9k tokens when it runs. Until then it costs about 111 tokens; SKILL.md has 392 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~111
When it runs · the whole SKILL.md, loaded when a task matches
~2.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Read, Write, Bash, Glob, Grep

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from giuseppe-trisciuoglio/developer-kit at commit fe73fb3, republished under its MIT licence (© giuseppe-trisciuoglio). 392 words, ~2,903 tokens.

Download SKILL.mdSave it as .claude/skills/unit-test-caching/SKILL.md (or your agent's skills folder).
name
unit-test-caching
description
Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict). Generates test code that mocks cache managers, verifies cache hit/miss behavior, tests cache key generation with SpEL expressions, validates eviction strategies, and checks conditional caching scenarios. Triggers: caching tests, test Spring cache, mock cache, Spring Boot caching, cache hit/miss verification, @Cacheable testing.
allowed-tools
Read, Write, Bash, Glob, Grep

Unit Testing Spring Caching

Overview

This skill provides patterns for unit testing Spring caching annotations (@Cacheable, @CacheEvict, @CachePut) without full Spring context. It covers cache hits/misses, invalidation, key generation, and conditional caching using in-memory ConcurrentMapCacheManager.

When to Use

  • Writing unit tests for @Cacheable method behavior
  • Verifying @CacheEvict cache invalidation works correctly
  • Testing @CachePut cache updates
  • Validating cache key generation from SpEL expressions
  • Testing conditional caching with unless/condition parameters
  • Mocking cache managers in fast unit tests without Redis

Instructions

  1. Configure in-memory CacheManager: Use ConcurrentMapCacheManager for tests
  2. Set up test fixtures: Mock repository and create service instance in @BeforeEach
  3. Verify repository call counts: Use times(n) assertions to confirm cache behavior
  4. Test cache hit: Call method twice, verify repository called once
  5. Test cache miss: Verify repository called on each invocation
  6. Test eviction: After @CacheEvict, verify repository called again on next read
  7. Test key generation: Verify compound keys from SpEL expressions
  8. Validate conditional caching: Test unless (null results) and condition (parameter-based)

Validation checkpoints:

  • Run test → If cache not working: verify @EnableCaching annotation present
  • If proxy issues: ensure method calls go through Spring proxy (no direct this calls)
  • If key mismatches: log actual cache key and compare with @Cacheable(key="...") expression

Examples

Maven
xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>
Gradle
kotlin
dependencies {
  implementation("org.springframework.boot:spring-boot-starter-cache")
  testImplementation("org.springframework.boot:spring-boot-starter-test")
}
Testing @Cacheable (Cache Hit/Miss)
java
// Service
@Service
public class UserService {
  private final UserRepository userRepository;

  public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  @Cacheable("users")
  public User getUserById(Long id) {
    return userRepository.findById(id).orElse(null);
  }
}

// Test
class UserServiceCachingTest {

  private UserRepository userRepository;
  private UserService userService;

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

  @Test
  void shouldCacheUserAfterFirstCall() {
    User user = new User(1L, "Alice");
    when(userRepository.findById(1L)).thenReturn(Optional.of(user));

    // First call - hits database
    User firstCall = userService.getUserById(1L);
    // Second call - hits cache
    User secondCall = userService.getUserById(1L);

    assertThat(firstCall).isEqualTo(secondCall);
    verify(userRepository, times(1)).findById(1L); // Only once due to cache
  }

  @Test
  void shouldInvokeRepositoryOnCacheMiss() {
    when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "Bob")));

    userService.getUserById(1L);
    userService.getUserById(1L);

    verify(userRepository, times(2)).findById(1L); // No caching occurred
  }
}
Testing @CacheEvict
java
// Service
@Service
public class ProductService {
  private final ProductRepository productRepository;

  public ProductService(ProductRepository productRepository) {
    this.productRepository = productRepository;
  }

  @Cacheable("products")
  public Product getProductById(Long id) {
    return productRepository.findById(id).orElse(null);
  }

  @CacheEvict("products")
  public void deleteProduct(Long id) {
    productRepository.deleteById(id);
  }
}

// Test
class ProductCacheEvictTest {

  private ProductRepository productRepository;
  private ProductService productService;

  @BeforeEach
  void setUp() {
    productRepository = mock(ProductRepository.class);
    productService = new ProductService(productRepository);
  }

  @Test
  void shouldEvictProductFromCacheWhenDeleted() {
    Product product = new Product(1L, "Laptop", 999.99);
    when(productRepository.findById(1L)).thenReturn(Optional.of(product));

    productService.getProductById(1L); // Cache the product
    productService.deleteProduct(1L); // Evict from cache

    // Repository called again after eviction
    productService.getProductById(1L);
    verify(productRepository, times(2)).findById(1L);
  }

  @Test
  void shouldClearAllEntriesWithAllEntriesTrue() {
    Product product1 = new Product(1L, "Laptop", 999.99);
    Product product2 = new Product(2L, "Mouse", 29.99);
    when(productRepository.findById(anyLong())).thenAnswer(i ->
      Optional.of(new Product(i.getArgument(0), "Product", 10.0)));

    productService.getProductById(1L);
    productService.getProductById(2L);

    // Use reflection or clear() on ConcurrentMapCache
    productService.clearAllProducts();

    productService.getProductById(1L);
    productService.getProductById(2L);

    verify(productRepository, times(4)).findById(anyLong());
  }
}
Testing @CachePut
java
@Service
public class OrderService {
  private final OrderRepository orderRepository;

  public OrderService(OrderRepository orderRepository) {
    this.orderRepository = orderRepository;
  }

  @Cacheable("orders")
  public Order getOrder(Long id) {
    return orderRepository.findById(id).orElse(null);
  }

  @CachePut(value = "orders", key = "#order.id")
  public Order updateOrder(Order order) {
    return orderRepository.save(order);
  }
}

class OrderCachePutTest {

  private OrderRepository orderRepository;
  private OrderService orderService;

  @BeforeEach
  void setUp() {
    orderRepository = mock(OrderRepository.class);
    orderService = new OrderService(orderRepository);
  }

  @Test
  void shouldUpdateCacheWhenOrderIsUpdated() {
    Order original = new Order(1L, "Pending", 100.0);
    Order updated = new Order(1L, "Shipped", 100.0);

    when(orderRepository.findById(1L)).thenReturn(Optional.of(original));
    when(orderRepository.save(updated)).thenReturn(updated);

    orderService.getOrder(1L);
    orderService.updateOrder(updated);

    // Next call returns updated version from cache
    Order cachedOrder = orderService.getOrder(1L);
    assertThat(cachedOrder.getStatus()).isEqualTo("Shipped");
  }
}
Testing Conditional Caching
java
@Service
public class DataService {
  private final DataRepository dataRepository;

  public DataService(DataRepository dataRepository) {
    this.dataRepository = dataRepository;
  }

  // Don't cache null results
  @Cacheable(value = "data", unless = "#result == null")
  public Data getData(Long id) {
    return dataRepository.findById(id).orElse(null);
  }

  // Only cache when id > 0
  @Cacheable(value = "users", condition = "#id > 0")
  public User getUser(Long id) {
    return dataRepository.findById(id).map(u -> new User(u.getId(), u.getName())).orElse(null);
  }
}

class ConditionalCachingTest {

  @Test
  void shouldNotCacheNullResults() {
    DataRepository dataRepository = mock(DataRepository.class);
    when(dataRepository.findById(999L)).thenReturn(Optional.empty());
    DataService service = new DataService(dataRepository);

    service.getData(999L);
    service.getData(999L);

    verify(dataRepository, times(2)).findById(999L); // Called twice - no caching
  }

  @Test
  void shouldNotCacheWhenConditionIsFalse() {
    DataRepository dataRepository = mock(DataRepository.class);
    when(dataRepository.findById(-1L)).thenReturn(Optional.of(new Data(-1L, "Test")));

    DataService service = new DataService(dataRepository);

    service.getUser(-1L);
    service.getUser(-1L);

    verify(dataRepository, times(2)).findById(-1L); // Condition "#id > 0" = false
  }
}
Testing Cache Keys with SpEL
java
@Service
public class InventoryService {
  private final InventoryRepository inventoryRepository;

  public InventoryService(InventoryRepository inventoryRepository) {
    this.inventoryRepository = inventoryRepository;
  }

  // Compound key: productId-warehouseId
  @Cacheable(value = "inventory", key = "#productId + '-' + #warehouseId")
  public InventoryItem getInventory(Long productId, Long warehouseId) {
    return inventoryRepository.findByProductAndWarehouse(productId, warehouseId);
  }
}

class CacheKeyTest {

  @Test
  void shouldUseCorrectCacheKeyForDifferentCombinations() {
    InventoryRepository repository = mock(InventoryRepository.class);
    InventoryItem item = new InventoryItem(1L, 1L, 100);
    when(repository.findByProductAndWarehouse(1L, 1L)).thenReturn(item);

    InventoryService service = new InventoryService(repository);

    // Same key: "1-1" - should cache
    service.getInventory(1L, 1L);
    service.getInventory(1L, 1L); // Cache hit
    verify(repository, times(1)).findByProductAndWarehouse(1L, 1L);

    // Different key: "2-1" - cache miss
    service.getInventory(2L, 1L); // Cache miss
    verify(repository, times(2)).findByProductAndWarehouse(any(), any());
  }
}
Show full SKILL.md (170 more words)Show less

Best Practices

  • Mock repository calls: Use verify(mock, times(n)) to assert cache behavior
  • Test both hit and miss scenarios: Don't just test the happy path
  • Clear cache state: Reset between tests to avoid flaky results
  • Use ConcurrentMapCacheManager: Fast, no external dependencies
  • Verify eviction: Always test that @CacheEvict actually invalidates cached data

Constraints and Warnings

  • @Cacheable requires proxy: Direct method calls (this.method()) bypass caching - use dependency injection
  • Cache key collisions: Compound keys from SpEL must be unique per dataset
  • Null caching: Null results are cached by default - use unless = "#result == null" to exclude
  • @CachePut always executes: Unlike @Cacheable, it always runs the method
  • Memory usage: In-memory caches grow unbounded - consider TTL for long-running tests
  • Thread safety: ConcurrentMapCacheManager is thread-safe; distributed caches may require additional config

Troubleshooting

IssueSolution
Cache not workingVerify @EnableCaching on test config
Proxy bypassUse autowired/constructor injection, not direct this calls
Key mismatchLog cache key with cache.getNativeKey() to debug SpEL
Flaky testsClear cache in @BeforeEach before each test

References

© giuseppe-trisciuoglio, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in plugins/developer-kit-java/skills/unit-test-caching of giuseppe-trisciuoglio/developer-kit.

Open the folder on GitHubat commit fe73fb3

Compare with similar skills

Unit Test Caching next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Unit Test Caching compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Unit Test Caching this skillgiuseppe-trisciuoglio/developer-kit357—~2.9kAutomated safety check: NotesMIT
Dotnet Backend Patternswshobson/agents40k8 repos~6.6kAutomated safety check: PassMIT
Springboot Patternsaffaan-m/ECC277k5 repos~2.5kAutomated safety check: PassMIT
Flowfile Debugging PlaybookEdwardvaneechoud/Flowfile389—~6.3kAutomated safety check: PassMIT
Multi Tenancyrrezartprebreza/spring-boot-skills301—~576Automated safety check: PassMIT
Spring Data Redisrrezartprebreza/spring-boot-skills301—~1.6kAutomated safety check: PassMIT

Similar skills

  • Master C/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications.

    40k GitHub starsUsed in 8 repos~6.6k tokens
    Backend & APIsAuto-check passed
  • Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging.

    277k GitHub starsUsed in 5 repos~2.5k tokens
    Backend & APIsAuto-check passed
  • Flowfile Debugging Playbook

    Edwardvaneechoud/Flowfile

    Symptom-to-cause triage playbook for Flowfile (core/worker/kernel/frontend/AI) — covers "no such table" DB cascades (two distinct causes), import-time Alembic migration corruption, silent…

    389 GitHub stars~6.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Multi Tenancy

    rrezartprebreza/spring-boot-skills

    A skill your agent uses when implementing tenant resolution, database or schema isolation, tenant-aware JPA, reactive tenant context, migrations, caching, jobs, or authorization in Spring Boot 3.

    301 GitHub stars~576 tokensUpdated 19 days ago
    Backend & APIsAuto-check passed
  • Spring Data Redis

    rrezartprebreza/spring-boot-skills

    A skill your agent uses when implementing caching, session storage, rate limiting, or any Redis integration.

    301 GitHub stars~1.6k tokensUpdated 19 days ago
    Backend & APIsAuto-check passed
  • Fastapi Endpoint

    davila7/claude-code-templates

    Plan and build production-ready FastAPI endpoints with async SQLAlchemy, Pydantic v2 models, dependency injection for auth, and pytest tests.

    33k GitHub stars~3.9k tokensUpdated yesterday
    Backend & APIsAuto-check passed

More from giuseppe-trisciuoglio/developer-kit

All 115 skills in this repo
  • Nestjs Drizzle Crud Generator

    giuseppe-trisciuoglio/developer-kit

    Generates complete CRUD modules for NestJS applications with Drizzle ORM.

    357 GitHub stars~1.3k tokensUpdated 1 mo ago
    Auto-check: notes
  • Spring Boot Actuator

    giuseppe-trisciuoglio/developer-kit

    Provides patterns to configure Spring Boot Actuator for production-grade monitoring, health probes, secured management endpoints, and Micrometer metrics across JVM services.

    357 GitHub stars~2.2k tokensUpdated 1 mo ago
    Auto-check: notes
  • Spring Boot Crud Patterns

    giuseppe-trisciuoglio/developer-kit

    Provides and generates complete CRUD workflows for Spring Boot 3 services.

    357 GitHub stars~2.5k tokensUpdated 1 mo ago
    Auto-check: notes
  • Spring Boot Security JWT

    giuseppe-trisciuoglio/developer-kit

    Provides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based…

    357 GitHub stars~3.9k tokensUpdated 1 mo ago
    Auto-check: notes
  • AWS CLI Beast

    giuseppe-trisciuoglio/developer-kit

    Provides advanced AWS CLI patterns for managing EC2, Lambda, S3, DynamoDB, RDS, VPC, IAM, and CloudWatch.

    357 GitHub stars~1.7k tokensUpdated 1 mo ago
    Auto-check: notes
  • PR Review Comments

    giuseppe-trisciuoglio/developer-kit

    Posts review findings from a JSON file as inline comments on a GitHub Pull Request, attaching each comment to its file and line.

    357 GitHub stars~1k tokensUpdated 1 mo ago
    Auto-check: notes

Works with

Questions about Unit Test Caching

What does Unit Test Caching do?

Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict). Unit Test Caching is an agent skill from giuseppe-trisciuoglio/developer-kit. Provides patterns for unit testing Spring Cache annotations (@Cacheable, @CachePut, @CacheEvict).

When should I use Unit Test Caching?

Unit Test Caching fits situations like: tasks that involve Caching; tasks that involve Unit testing; tasks that involve Backend development.

How do I install Unit Test Caching in Claude Code?

Run `npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-caching -a claude-code`. Or copy the skill folder (plugins/developer-kit-java/skills/unit-test-caching in giuseppe-trisciuoglio/developer-kit) into .claude/skills/unit-test-caching in your project. Claude Code loads it when a task matches its description.

How do I install Unit Test Caching in Codex?

Run `npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-caching -a codex`. Or copy the skill folder (plugins/developer-kit-java/skills/unit-test-caching in giuseppe-trisciuoglio/developer-kit) into .agents/skills/unit-test-caching in your project. Codex loads it when a task matches its description.

Can I use Unit Test Caching in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add giuseppe-trisciuoglio/developer-kit --skill unit-test-caching -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/unit-test-caching, .gemini/skills/unit-test-caching, .github/skills/unit-test-caching and .opencode/skills/unit-test-caching in your project.

What does Unit Test Caching need to run?

SKILL.md names no scripts, command-line tools or credentials: Unit Test Caching is instructions for the agent only. Its frontmatter pre-approves these tools: Read, Write, Bash, Glob, Grep.

Does Unit Test Caching access the network?

SKILL.md names 1 domain. As links in the text: docs.spring.io. This is read from the text; nothing was executed.

Is Unit Test Caching safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Unit Test Caching use?

Unit Test Caching is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Unit Test Caching use?

About 2.9k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Unit Test Caching?

Skills that share tags, products or a category with Unit Test Caching: Dotnet Backend Patterns (wshobson/agents, 40k stars), Springboot Patterns (affaan-m/ECC, 277k stars), Flowfile Debugging Playbook (Edwardvaneechoud/Flowfile, 389 stars) and Multi Tenancy (rrezartprebreza/spring-boot-skills, 301 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Unit Test Caching?

giuseppe-trisciuoglio (a GitHub user) maintains it in giuseppe-trisciuoglio/developer-kit, which has 357 GitHub stars. The repository holds 115 skills in this directory. The repository was last updated on September 10, 2026.

Source: giuseppe-trisciuoglio/developer-kit on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.