Provides patterns for unit testing Spring `@Scheduled` and `@Async` methods using JUnit 5, CompletableFuture, Awaitility, and Mockito. Covers mocking task execution and timing, verifying execution counts, testing cron expressions, validating retry behavior, and simulating thread pool behavior.
SkillScore96Maintained
Automatic
◆QA & Test Engineering pack
Last verified 8/21/2026
What it changes
Passed 24 of 25 test cases with the skill, and 17 of 25 without it.
Without skill68%
With skill96%
Checks it passed that the model alone missed
The response recommends decreasing the pollInterval value.
The test asserts state changes before calling Mockito verify.
The test retrieves the future result using get with a timeout.
and 4 more in the full report
7 fixed17 passed either way1 still failing0 broke
Pass-rate lift
+28 pp
Tokens
+34%
Agent turns
0%
Response time
-27%
Model gemini-3.6-flashMeasured 8/21/2026v124 of 25 cases passed with skill
Tokens, turns and time describe resource use, not a dollar price.
See it in action
One of 7 test cases the skill fixed. Same model, same prompt, with and without the skill.
1 of 7
Prompt
In a unit test for an async method returning `CompletableFuture.completedFuture("SUCCESS")`, how should I assert the returned string using AssertJ?
What was checked, without and with the skill
Checked
Without skill
With skill
The test retrieves the future result using get with a timeout.
Missed
Passed
The test asserts the result using AssertJ.
Passed
Passed
case-19 · gemini-3.6-flash · 8/21/2026 · answers are capped and redacted
What's inside
The instructions your model reads when the skill loads.
SKILL.md118 lines2 files
Unit Testing @Scheduled and @Async Methods
Overview
Patterns for unit testing Spring @Scheduled and @Async methods with JUnit 5. Test CompletableFuture results, use Awaitility for race conditions, mock scheduled task execution, and validate error handling — without waiting for real scheduling intervals.
When to Use
Testing @Scheduled method logic
Testing @Async method behavior
Verifying CompletableFuture results
Testing async error handling
Testing cron expression logic without waiting for actual scheduling
Validating thread pool behavior and execution counts
Testing background task logic in isolation
Instructions
Call @Async methods directly — bypass Spring's async proxy; the annotation is irrelevant in unit tests
Mock dependencies with @Mock and @InjectMocks (Mockito)
Wait for completion — use CompletableFuture.get(timeout, unit) or await().atMost(...).untilAsserted(...)
Call @Scheduled methods directly — do not wait for cron/fixedRate; the annotation is ignored in unit tests
Test exception paths — verify ExecutionException wrapping on CompletableFuture.get()
Validation checkpoints:
After CompletableFuture.get(), assert the returned value before verifying mock interactions
If ExecutionException is thrown, check .getCause() to identify the root exception
If Awaitility times out, increase atMost() duration or reduce pollInterval() until the condition is reachable
After multiple task invocations, assert execution counts before verify() calls
Examples
Key patterns — complete examples in references/examples.md:
// @Async: call directly, wait with CompletableFuture.get(timeout, unit)
@Service
class EmailService {
@Async
public CompletableFuture<Boolean> sendEmailAsync(String to) {