The test failure that taught me to write better debugging prompts was a flaky integration test that failed roughly one CI run in five. I pasted the assertion error into an AI assistant and got back five generic guesses, none right. Then I pasted the complete picture — full stack trace, the whole test class, the production method, and the fact that it only failed in parallel runs — and the diagnosis (shared static state in a test fixture) came back in one reply. The lesson: with debugging, the prompt is mostly evidence collection.
This post collects 10 prompts for diagnosing and fixing broken, flaky, or misbehaving JUnit 6 tests, each structured around the evidence that particular failure type needs — so the AI diagnoses the root cause instead of guessing. Tested with Claude Sonnet 4 and GPT-4o against JUnit 6.0, Mockito 5.x, and Spring Boot 3.4 failures.
For complementary reading, see Debugging JUnit 6 Tests: Fix Failures Like a Pro and How to Fix Flaky Tests in JUnit 6.
Give the AI the Evidence, Not the Symptom
Every prompt below is built around the same principle: a debugging assistant is only as good as the evidence you hand it. “My test fails sometimes” gets you guesses; the items below get you a diagnosis. Collect them before pasting anything:
- The full stack trace (not just the error message)
- The failing test method (complete, not excerpted)
- The production method under test
- Any relevant configuration (Spring context, Testcontainers setup)
- Whether the failure is consistent or intermittent
Prompt 1: Diagnose and Fix a Failing assertEquals
When to use: A test is failing with “expected X but was Y” and you are not immediately sure whether the bug is in the production code or the test assertion.
Diagnose why the following JUnit 6 test is failing and provide a fix.
Failure output:
[PASTE THE FULL STACK TRACE AND FAILURE MESSAGE HERE]
Example:
org.opentest4j.AssertionFailedError: Order status should be CONFIRMED
expected:
but was:
at com.example.OrderServiceTest.placingValidOrderConfirmsIt(OrderServiceTest.java:47)
Failing test method:
[PASTE THE COMPLETE TEST METHOD HERE]
Production method under test:
[PASTE THE PRODUCTION METHOD HERE]
Analysis required:
1. Is the assertion in the wrong order (actual before expected)?
2. Is the expected value wrong for the business logic?
3. Is the production code returning the wrong value (genuine bug)?
4. Is there a timing issue (async operation not complete when assertion runs)?
5. Is there missing setup in @BeforeEach that causes unexpected initial state?
Provide:
- Root cause diagnosis
- Whether this is a TEST bug or a PRODUCTION CODE bug
- The corrected test (or the corrected production code if it is a code bug)
- A more informative assertion message to make future failures clearer
Prompt 2: Fix NullPointerException in Test
When to use: Your test throws a NullPointerException at an unexpected line — usually caused by uninitialised mocks, missing setup, or a method returning null when a non-null value was expected.
Fix the NullPointerException in the following JUnit 6 test.
Full stack trace:
[PASTE COMPLETE STACK TRACE HERE]
Failing test class (complete):
[PASTE THE COMPLETE TEST CLASS HERE]
Production class under test:
[PASTE THE PRODUCTION CLASS HERE]
Checklist to investigate:
1. Is @ExtendWith(MockitoExtension.class) missing? (causes @Mock fields to be null)
2. Is there a @Mock field that was not declared but is used in the class under test?
3. Is a stub returning null when it should return a default object?
(e.g., when(repo.findById(1L)).thenReturn(null) instead of Optional.empty())
4. Is @BeforeEach not creating the object under test (orderService = new OrderService(...))?
5. Is the test calling a method on the RESULT before asserting it is not null?
6. Is there a @BeforeAll that should be static but is not?
Provide:
- The exact null reference causing the NPE
- Whether @ExtendWith, @BeforeEach, or a stub is the root cause
- The fully corrected test class
- Explanation of why the fix works
Prompt 3: Fix UnnecessaryStubbingException from Mockito
When to use: Mockito’s strict mode is throwing UnnecessaryStubbingException because a stub was declared but the stubbed method was never called during the test.
Fix the following UnnecessaryStubbingException in this JUnit 6 + Mockito test.
Error message:
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbing detected in test class [TestClassName]
1. [stubbing declaration line number]
Complete test class:
[PASTE THE COMPLETE TEST CLASS HERE]
Production class:
[PASTE THE PRODUCTION CLASS HERE]
Analysis required:
1. Identify which when().thenReturn() stub is declared but the method is never called
2. Determine WHY it is never called:
a) The test exercises a code path that skips this call
b) The stubbed method name/signature no longer matches the production code
c) The stub was added for a DIFFERENT test case and copied here accidentally
d) The production code was refactored and no longer calls this dependency
Fix options to consider (choose the most appropriate):
Option A: Remove the unnecessary stub entirely
Option B: Add lenient() if the stub IS needed in some but not all configurations:
lenient().when(service.method()).thenReturn(value);
Option C: Move the stub to @BeforeEach only if it is needed by ALL tests in the class
Option D: Keep the stub but fix the test to actually exercise the code path that calls it
Provide the corrected test class with explanation of which option was chosen and why.
Prompt 4: Debug Flaky Test That Fails Intermittently
When to use: A test passes most of the time but fails occasionally, especially in parallel CI runs — the classic symptom of shared state, timing, or non-deterministic data.
Diagnose and fix the following flaky JUnit 6 test that passes sometimes and fails sometimes.
Test class (complete):
[PASTE THE COMPLETE TEST CLASS HERE]
Failure output (from a failing run):
[PASTE THE FAILURE OUTPUT WHEN IT FAILS]
Known facts about failure pattern:
- Fails approximately: [e.g., "1 in 5 runs", "only in CI", "only when run in parallel"]
- When it fails, the error is: [e.g., "assertion failure", "timeout", "database constraint violation"]
Flakiness root cause checklist to analyse:
1. Static mutable state? (static counters, static lists, static connection pools)
2. Thread.sleep() with too-short duration? → Replace with Awaitility
3. Hardcoded port number? → Replace with RANDOM_PORT
4. Tests sharing database state without rollback? → Add @Transactional or explicit cleanup
5. Time-dependent assertions (LocalDate.now(), System.currentTimeMillis())?
→ Inject a Clock and use a fixed clock in tests
6. File path collisions in parallel runs? → Use @TempDir per test
7. Random data without fixed seed? → Use new Random(fixedSeed)
8. Assertions on async operations without waiting? → Add Awaitility polling
Produce:
- Root cause identification
- The fixed test class
- A unit test that would ALWAYS reproduce the failure to verify the fix
Prompt 5: Fix “0 Tests Found” / Test Not Discovered
When to use: Maven or Gradle reports “0 tests run” or “no tests found” even though your test class and methods clearly exist and look correct.
Diagnose why JUnit 6 is not discovering the following test class.
Build output showing the problem:
[PASTE THE MAVEN/GRADLE OUTPUT, e.g.:
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0]
Test class that is not being discovered:
[PASTE THE COMPLETE TEST CLASS HERE]
pom.xml or build.gradle (relevant sections):
[PASTE THE SUREFIRE/GRADLE TEST CONFIGURATION HERE]
Discovery checklist to verify:
1. Is junit-jupiter-engine on the classpath? (needed for test discovery)
Check: is 'junit-jupiter' aggregator used, or only 'junit-jupiter-api'?
2. Is Maven Surefire version >= 2.22.0? (older versions don't support JUnit Platform)
3. Does Gradle have useJUnitPlatform() in the test block?
4. Does the test class name match the discovery pattern (*Test, Test*, *Tests)?
5. Is the test class in src/test/java (not src/main/java)?
6. Does the test class have a non-default constructor without a matching TestInstanceFactory?
7. Are there any tag filters in Surefire/Gradle that exclude this test?
8. Is the test class inside a package that is excluded by a Surefire excludes rule?
Provide:
- The specific configuration problem
- The corrected pom.xml or build.gradle
- Command to verify discovery is now working
Prompt 6: Fix Spring Context Startup Failure in @SpringBootTest
When to use: Your integration tests fail before a single assertion runs, with a Spring ApplicationContext startup error.
Diagnose and fix the following Spring ApplicationContext startup failure in a JUnit 6 test.
Full stack trace (from context startup failure):
[PASTE THE COMPLETE ERROR INCLUDING Caused by: chain]
Test class:
[PASTE THE TEST CLASS HERE]
application.properties or application-test.properties (if relevant):
[PASTE RELEVANT CONFIGURATION HERE]
Common causes to check:
1. Missing @MockBean for a bean that has no test configuration and cannot be auto-created
(e.g., a bean that requires database connection, external API, or missing property)
2. Missing test properties:
spring.datasource.url not configured for @SpringBootTest without Testcontainers
3. @ActiveProfiles("test") not set — production properties being loaded with real values
4. Circular dependency detected only at test time due to @MockBean interactions
5. A @ComponentScan picking up test classes that interfere with the context
6. Missing Testcontainers @DynamicPropertySource that should provide the datasource URL
7. Port already in use — use RANDOM_PORT instead of DEFINED_PORT
Provide:
- Root cause of the startup failure (which bean failed to create and why)
- The corrected test class
- Any application-test.properties entries needed
- Whether this is a test configuration issue or a production bean configuration issue
Prompt 7: Fix AssertionError with Wrong Argument Order
When to use: Your test failure messages are confusing or backwards — “expected: PENDING but was: CONFIRMED” when you know CONFIRMED is what you want. Classic swapped argument order.
Review the following JUnit 6 test class and fix all instances of swapped assertEquals arguments.
The correct order in JUnit 6 is:
assertEquals(EXPECTED_VALUE, actualValue, "message")
- EXPECTED: the value you know in advance (literal, constant, or known variable)
- ACTUAL: the value returned by the code under test (method call result)
Common wrong patterns to find and fix:
- assertEquals(result, OrderStatus.CONFIRMED) → assertEquals(OrderStatus.CONFIRMED, result)
- assertEquals(service.getCount(), 5) → assertEquals(5, service.getCount())
- assertTrue(5 == list.size()) → assertEquals(5, list.size())
Also fix:
- Any assertion without a descriptive message → add a message as the third argument
- Any assertTrue(a.equals(b)) → replace with assertEquals(a, b, "message")
- Any assertFalse(a == null) → replace with assertNotNull(a, "message")
After fixing argument order, also add descriptive failure messages to every assertion:
assertEquals(OrderStatus.CONFIRMED, order.getStatus(),
"Order should be CONFIRMED after successful payment authorisation")
Test class to audit and fix:
[PASTE YOUR TEST CLASS HERE]
Prompt 8: Fix Tests Broken by Testcontainers / Docker Issues
When to use: Tests using Testcontainers are failing in CI with container startup errors, connection refused, or image pull failures.
Fix the following Testcontainers test failures in JUnit 6.
Error output from failing test:
[PASTE THE COMPLETE ERROR, e.g.:
org.testcontainers.containers.ContainerLaunchException: Container startup failed
Caused by: com.github.dockerjava.api.exception.DockerException: connect to docker daemon failed]
OR:
[java.sql.SQLNonTransientConnectionException: Could not create connection to database server]
Test class with Testcontainers setup:
[PASTE THE COMPLETE TEST CLASS HERE]
CI environment:
[DESCRIBE CI, e.g.: "GitHub Actions ubuntu-latest", "Jenkins on AWS EC2"]
Common CI-specific fixes to apply:
1. Docker not running → add Docker check: assumeTrue(DockerClientFactory.instance().isDockerAvailable())
2. Ryuk container blocked in CI → add environment variable: TESTCONTAINERS_RYUK_DISABLED=true
3. Image not pulled → use .withImagePullPolicy(PullPolicy.alwaysPull()) for first run
4. Container startup timeout too short → add .withStartupTimeout(Duration.ofSeconds(120))
5. Wrong Docker host in CI → set DOCKER_HOST=unix:///var/run/docker.sock in environment
6. @Container non-static → causing container restart per test method (slow but valid)
→ make it static for better performance: static final PostgreSQLContainer postgres = ...
7. Missing @DynamicPropertySource → Spring datasource not pointing to container's port
Provide:
- Root cause of the container failure
- The corrected test class and/or CI environment configuration
- The @DynamicPropertySource method if missing
Prompt 9: Fix MockMvc Test Returning Wrong HTTP Status
When to use: Your @WebMvcTest or MockMvc integration test is asserting a specific HTTP status code but receiving a different one — 404 instead of 200, 500 instead of 400, etc.
Debug and fix the following MockMvc test that is receiving the wrong HTTP status code.
Failing test:
[PASTE THE FAILING TEST METHOD]
Failure output:
[PASTE THE FAILURE, e.g.:
MockMvcResultMatchers$StatusResultMatchers$1.match(MockMvcResultMatchers.java:...)
Status expected:<200> but was:<404>]
Controller class:
[PASTE THE CONTROLLER CLASS]
Service mock setup (if any):
[PASTE THE @MockBean STUBS]
Debug checklist:
1. Is the URL in the test exactly matching the @RequestMapping/@GetMapping on the controller?
(including case, trailing slash, path variables)
2. Is the controller class in @WebMvcTest([ControllerClass].class)?
(if the wrong class is listed, the correct controller is not loaded)
3. Is a required @MockBean missing? (null service causes NullPointerException → 500)
4. Is the request Content-Type set correctly for POST/PUT? (missing causes 415)
5. Is the @RequestBody validation failing? (invalid body causes 400 not 200)
6. Is there a Spring Security configuration loading that blocks the endpoint? (causes 401/403)
7. Is the stub returning the right type? (wrong return type causes ClassCastException → 500)
Provide:
- The root cause of the wrong status code
- The corrected test with the fix applied
- andDo(print()) added to show the full request/response for debugging
- How to verify the fix is correct
Prompt 10: Comprehensive Test Failure Triage for a Broken Build
When to use: CI is broken with multiple test failures across several classes after a recent change, and you need a systematic triage to identify which are real bugs vs test configuration issues vs environment problems.
Triage the following multiple JUnit 6 test failures from a broken CI build.
Full Maven/Gradle test output showing all failures:
[PASTE THE COMPLETE BUILD OUTPUT HERE]
Recent production code changes (git diff summary):
[DESCRIBE WHAT CHANGED, e.g.:
- Renamed method 'calculatePrice' to 'computeFinalPrice' in PricingService
- Added new required constructor parameter: Clock clock
- Changed return type of OrderService.create() from Order to CompletableFuture]
For each failing test, classify into one of:
A) PRODUCTION CODE BUG — the test is correct, production code introduced a regression
B) TEST NEEDS UPDATE — the production code change was intentional, test needs updating
C) TEST CONFIGURATION — broken setup (wrong mock, missing @BeforeEach, wrong annotation)
D) ENVIRONMENT ISSUE — CI-specific (port, Docker, database connection)
E) COMPILATION ERROR — import or signature mismatch after refactoring
Output format:
For each failing test:
1. Test name:
2. Classification: [A/B/C/D/E]
3. Root cause:
4. Fix required:
5. Priority: [CRITICAL - blocks release / HIGH - fix before merge / LOW - cosmetic]
Then provide:
- The corrected test classes for all Type B and C failures
- A list of production code locations to investigate for Type A failures
- CI configuration changes needed for Type D failures
Reading a Stack Trace Like a Pro: Quick Reference
Before using any of these prompts, apply this three-step stack trace reading technique:
- Find your package — scan the stack trace for lines containing your package name (e.g.,
com.example). Ignore all JUnit, Mockito, and Spring framework frames above them. - Read the first cause — the bottom-most “Caused by:” is the root cause. Everything above it is the propagation chain.
- Read the message — the error message before the stack trace often contains the exact expected vs actual values or the missing bean name. It is the most actionable line.
Frequently Asked Questions (FAQs)
Q1: These prompts ask for the full stack trace. How much of it should I paste?
Paste everything from the exception class name through the first occurrence of your package name in the stack. Include all “Caused by:” chains — they are often more informative than the outer exception. If the stack trace is very long (100+ lines), cut it after the first 20 lines of framework frames since those repeat the same information.
Q2: What if the AI’s diagnosis is wrong?
Provide more context and correct the AI. Say: “That is not the root cause. The method IS being called (I verified with a debug breakpoint). The issue is different — here is additional information: [add details].” AI tools are excellent at reasoning through failure scenarios when given precise information, but they sometimes need correction and guidance when their initial hypothesis is wrong. Treat it as a collaborative debugging session.
Q3: Can I use Prompt 10 for production incidents, not just CI failures?
Yes, but adapt it: replace “recent production code changes (git diff)” with “recent deployment changes” and change the classification to include “REAL PRODUCTION BUG — tests missed this” as a category. Post-incident, add tests for the bug before the fix (test-driven bugfixing) to ensure it never regresses.
Q4: How do I share test failures with the AI securely if tests contain sensitive data?
Anonymise the data before pasting. Replace real emails, customer names, and financial figures with clearly fake placeholders: [email protected], John Test, 99.99. The AI needs the structure of the failing test and the stack trace — not the actual business data values. Keep class names, method names, and package names intact as those are essential for diagnosis.
Q5: After fixing a flaky test with these prompts, how do I verify it is truly fixed?
Run the fixed test with @RepeatedTest(20) locally. If it passes all 20 times, it is likely fixed. In CI, run the test in parallel mode (junit.jupiter.execution.parallel.enabled=true) alongside the rest of the suite — parallel execution surfaces shared state issues more reliably than sequential runs. Also enable random test execution order (junit.jupiter.execution.order.random=true) to expose any remaining order dependency. See How to Fix Flaky Tests in JUnit 6 for a complete verification strategy.
See Also
- Debugging JUnit 6 Tests: Fix Failures Like a Pro
- How to Fix Flaky Tests in JUnit 6 (Root Causes + Solutions)
- Common JUnit Testing Mistakes and How to Avoid Them
- JUnit 6 with Testcontainers: Real Database Integration Testing
- JUnit 6 Nullability: @Nullable, @NonNull and @NullMarked Explained
- JUnit 6 Tutorial: Complete Series Index
Conclusion
Debugging test failures is faster and less frustrating when you give the AI the right information. These 10 prompts are structured to provide the AI with exactly what it needs: the failure output, the failing test, the production code, and a targeted checklist of likely root causes. Use them as a systematic debugging toolkit — apply the specific prompt that matches your failure type, review the AI diagnosis critically, apply the fix, and verify with repeated runs. The combination of your domain knowledge and AI diagnostic speed is more powerful than either alone.