{"id":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","shortId":"9LvuHQ","kind":"skill","title":"spring-boot-testing","tagline":"Expert Spring Boot 4 testing specialist that selects the best Spring Boot testing techniques for your situation with Junit 6 and AssertJ.","description":"# Spring Boot Testing\n\nThis skill provides expert guide for testing Spring Boot 4 applications with modern patterns and best practices.\n\n## Core Principles\n\n1. **Test Pyramid**: Unit (fast) > Slice (focused) > Integration (complete)\n2. **Right Tool**: Use the narrowest slice that gives you confidence\n3. **AssertJ Style**: Fluent, readable assertions over verbose matchers\n4. **Modern APIs**: Prefer MockMvcTester and RestTestClient over legacy alternatives\n\n## Which Test Slice?\n\n| Scenario | Annotation | Reference |\n|----------|------------|-----------|\n| Controller + HTTP semantics | `@WebMvcTest` | [references/webmvctest.md](references/webmvctest.md) |\n| Repository + JPA queries | `@DataJpaTest` | [references/datajpatest.md](references/datajpatest.md) |\n| REST client + external APIs | `@RestClientTest` | [references/restclienttest.md](references/restclienttest.md) |\n| JSON (de)serialization | `@JsonTest` | [references/test-slices-overview.md](references/test-slices-overview.md) |\n| Full application | `@SpringBootTest` | [references/test-slices-overview.md](references/test-slices-overview.md) |\n\n## Test Slices Reference\n\n- [references/test-slices-overview.md](references/test-slices-overview.md) - Decision matrix and comparison\n- [references/webmvctest.md](references/webmvctest.md) - Web layer with MockMvc\n- [references/datajpatest.md](references/datajpatest.md) - Data layer with Testcontainers\n- [references/restclienttest.md](references/restclienttest.md) - REST client testing\n\n## Testing Tools Reference\n\n- [references/mockmvc-tester.md](references/mockmvc-tester.md) - AssertJ-style MockMvc (3.2+)\n- [references/mockmvc-classic.md](references/mockmvc-classic.md) - Traditional MockMvc (pre-3.2)\n- [references/resttestclient.md](references/resttestclient.md) - Spring Boot 4+ REST client\n- [references/mockitobean.md](references/mockitobean.md) - Mocking dependencies\n\n## Assertion Libraries\n\n- [references/assertj-basics.md](references/assertj-basics.md) - Scalars, strings, booleans, dates\n- [references/assertj-collections.md](references/assertj-collections.md) - Lists, Sets, Maps, arrays\n\n## Testcontainers\n\n- [references/testcontainers-jdbc.md](references/testcontainers-jdbc.md) - PostgreSQL, MySQL, etc.\n\n## Test Data Generation\n\n- [references/instancio.md](references/instancio.md) - Generate complex test objects (3+ properties)\n\n## Performance & Migration\n\n- [references/context-caching.md](references/context-caching.md) - Speed up test suites\n- [references/sb4-migration.md](references/sb4-migration.md) - Spring Boot 4.0 changes\n\n## Quick Decision Tree\n\n```\nTesting a controller endpoint?\n  Yes → @WebMvcTest with MockMvcTester\n\nTesting repository queries?\n  Yes → @DataJpaTest with Testcontainers (real DB)\n\nTesting business logic in service?\n  Yes → Plain JUnit + Mockito (no Spring context)\n\nTesting external API client?\n  Yes → @RestClientTest with MockRestServiceServer\n\nTesting JSON mapping?\n  Yes → @JsonTest\n\nNeed full integration test?\n  Yes → @SpringBootTest with minimal context config\n```\n\n## Spring Boot 4 Highlights\n\n- **RestTestClient**: Modern alternative to TestRestTemplate\n- **@MockitoBean**: Replaces @MockBean (deprecated)\n- **MockMvcTester**: AssertJ-style assertions for web tests\n- **Modular starters**: Technology-specific test starters\n- **Context pausing**: Automatic pausing of cached contexts (Spring Framework 7)\n\n## Testing Best Practices\n\n### Code Complexity Assessment\n\nWhen a method or class is too complex to test effectively:\n\n1. **Analyze complexity** - If you need more than 5-7 test cases to cover a single method, it's likely too complex\n2. **Recommend refactoring** - Suggest breaking the code into smaller, focused functions\n3. **User decision** - If the user agrees to refactor, help identify extraction points\n4. **Proceed if needed** - If the user decides to continue with the complex code, implement tests despite the difficulty\n\n**Example of refactoring recommendation:**\n```java\n// Before: Complex method hard to test\npublic Order processOrder(OrderRequest request) {\n  // Validation, discount calculation, payment, inventory, notification...\n  // 50+ lines of mixed concerns\n}\n\n// After: Refactored into testable units\npublic Order processOrder(OrderRequest request) {\n  validateOrder(request);\n  var order = createOrder(request);\n  applyDiscount(order);\n  processPayment(order);\n  updateInventory(order);\n  sendNotification(order);\n  return order;\n}\n```\n\n### Avoid Code Redundancy\n\nCreate helper methods for commonly used objects and mock setup to enhance readability and maintainability.\n\n### Test Organization with @DisplayName\n\nUse descriptive display names to clarify test intent:\n\n```java\n@Test\n@DisplayName(\"Should calculate discount for VIP customer\")\nvoid shouldCalculateDiscountForVip() { }\n\n@Test\n@DisplayName(\"Should reject order when customer has insufficient credit\")\nvoid shouldRejectOrderForInsufficientCredit() { }\n```\n\n### Test Coverage Order\n\nAlways structure tests in this order:\n\n1. **Main scenario** - The happy path, most common use case\n2. **Other paths** - Alternative valid scenarios, edge cases\n3. **Exceptions/Errors** - Invalid inputs, error conditions, failure modes\n\n### Test Production Scenarios\n\nWrite tests with real production scenarios in mind. This makes tests more relatable and helps understand code behavior in actual production cases.\n\n### Test Coverage Goals\n\nAim for 80% code coverage as a practical balance between quality and effort. Higher coverage is beneficial but not the only goal.\n\nUse Jacoco maven plugin for coverage reporting and tracking.\n\n\n**Coverage Rules:**\n- 80+% coverage minimum\n- Focus on meaningful assertions, not just execution\n\n**What to Prioritize:**\n1. Business-critical paths (payment processing, order validation)\n2. Complex algorithms (pricing, discount calculations)\n3. Error handling (exceptions, edge cases)\n4. Integration points (external APIs, databases)\n\n## Dependencies (Spring Boot 4)\n\n```xml\n<dependency>\n  <groupId>org.springframework.boot</groupId>\n  <artifactId>spring-boot-starter-test</artifactId>\n  <scope>test</scope>\n</dependency>\n\n<!-- For WebMvc tests -->\n<dependency>\n  <groupId>org.springframework.boot</groupId>\n  <artifactId>spring-boot-starter-webmvc-test</artifactId>\n  <scope>test</scope>\n</dependency>\n\n<!-- For Testcontainers -->\n<dependency>\n  <groupId>org.springframework.boot</groupId>\n  <artifactId>spring-boot-testcontainers</artifactId>\n  <scope>test</scope>\n</dependency>\n```","tags":["spring","boot","testing","awesome","copilot","github","agent-skills","agents","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"capabilities":["skill","source-github","skill-spring-boot-testing","topic-agent-skills","topic-agents","topic-awesome","topic-custom-agents","topic-github-copilot","topic-hacktoberfest","topic-prompt-engineering"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/spring-boot-testing","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add github/awesome-copilot","source_repo":"https://github.com/github/awesome-copilot","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 33270 github stars · SKILL.md body (6,469 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:52:25.669Z","embedding":null,"createdAt":"2026-04-18T20:31:42.661Z","updatedAt":"2026-05-18T18:52:25.669Z","lastSeenAt":"2026-05-18T18:52:25.669Z","tsv":"'-3.2':165 '-7':341 '1':49,332,512,612 '2':58,354,522,621 '3':69,206,365,530,627 '3.2':159 '4':8,39,78,170,279,378,633,642 '4.0':220 '5':340 '50':419 '6':24 '7':314 '80':568,599 'actual':560 'agre':371 'aim':566 'algorithm':623 'altern':87,283,525 'alway':506 'analyz':333 'annot':92 'api':80,109,256,637 'applic':40,120 'applydiscount':440 'array':190 'assert':74,177,294,605 'assertj':26,70,156,292 'assertj-styl':155,291 'assess':320 'automat':307 'avoid':450 'balanc':574 'behavior':558 'benefici':582 'best':14,45,316 'boolean':183 'boot':3,7,16,28,38,169,219,278,641,647,654,662 'break':358 'busi':243,614 'business-crit':613 'cach':310 'calcul':415,484,626 'case':343,521,529,562,632 'chang':221 'clarifi':477 'class':325 'client':107,148,172,257 'code':318,360,391,451,557,569 'common':457,519 'comparison':132 'complet':57 'complex':203,319,328,334,353,390,403,622 'concern':423 'condit':535 'confid':68 'config':276 'context':253,275,305,311 'continu':387 'control':94,227 'core':47 'cover':345 'coverag':504,564,570,580,593,597,600 'creat':453 'createord':438 'credit':500 'critic':615 'custom':488,497 'data':141,198 'databas':638 'datajpatest':103,237 'date':184 'db':241 'de':114 'decid':385 'decis':129,223,367 'depend':176,639 'deprec':289 'descript':473 'despit':394 'difficulti':396 'discount':414,485,625 'display':474 'displaynam':471,482,492 'edg':528,631 'effect':331 'effort':578 'endpoint':228 'enhanc':464 'error':534,628 'etc':196 'exampl':397 'except':630 'exceptions/errors':531 'execut':608 'expert':5,33 'extern':108,255,636 'extract':376 'failur':536 'fast':53 'fluent':72 'focus':55,363,602 'framework':313 'full':119,268 'function':364 'generat':199,202 'give':66 'goal':565,587 'guid':34 'handl':629 'happi':516 'hard':405 'help':374,555 'helper':454 'higher':579 'highlight':280 'http':95 'identifi':375 'implement':392 'input':533 'insuffici':499 'integr':56,269,634 'intent':479 'invalid':532 'inventori':417 'jacoco':589 'java':401,480 'jpa':101 'json':113,263 'jsontest':116,266 'junit':23,249 'layer':136,142 'legaci':86 'librari':178 'like':351 'line':420 'list':187 'logic':244 'main':513 'maintain':467 'make':550 'map':189,264 'matcher':77 'matrix':130 'maven':590 'meaning':604 'method':323,348,404,455 'migrat':209 'mind':548 'minim':274 'minimum':601 'mix':422 'mock':175,461 'mockbean':288 'mockito':250 'mockitobean':286 'mockmvc':138,158,163 'mockmvctest':82,232,290 'mockrestserviceserv':261 'mode':537 'modern':42,79,282 'modular':298 'mysql':195 'name':475 'narrowest':63 'need':267,337,381 'notif':418 'object':205,459 'order':409,430,437,441,443,445,447,449,495,505,511,619 'orderrequest':411,432 'org.springframework.boot':644,651,659 'organ':469 'path':517,524,616 'pattern':43 'paus':306,308 'payment':416,617 'perform':208 'plain':248 'plugin':591 'point':377,635 'postgresql':194 'practic':46,317,573 'pre':164 'prefer':81 'price':624 'principl':48 'priorit':611 'proceed':379 'process':618 'processord':410,431 'processpay':442 'product':539,545,561 'properti':207 'provid':32 'public':408,429 'pyramid':51 'qualiti':576 'queri':102,235 'quick':222 'readabl':73,465 'real':240,544 'recommend':355,400 'redund':452 'refactor':356,373,399,425 'refer':93,126,152 'references/assertj-basics.md':179,180 'references/assertj-collections.md':185,186 'references/context-caching.md':210,211 'references/datajpatest.md':104,105,139,140 'references/instancio.md':200,201 'references/mockitobean.md':173,174 'references/mockmvc-classic.md':160,161 'references/mockmvc-tester.md':153,154 'references/restclienttest.md':111,112,145,146 'references/resttestclient.md':166,167 'references/sb4-migration.md':216,217 'references/test-slices-overview.md':117,118,122,123,127,128 'references/testcontainers-jdbc.md':192,193 'references/webmvctest.md':98,99,133,134 'reject':494 'relat':553 'replac':287 'report':594 'repositori':100,234 'request':412,433,435,439 'rest':106,147,171 'restclienttest':110,259 'resttestcli':84,281 'return':448 'right':59 'rule':598 'scalar':181 'scenario':91,514,527,540,546 'select':12 'semant':96 'sendnotif':446 'serial':115 'servic':246 'set':188 'setup':462 'shouldcalculatediscountforvip':490 'shouldrejectorderforinsufficientcredit':502 'singl':347 'situat':21 'skill':31 'skill-spring-boot-testing' 'slice':54,64,90,125 'smaller':362 'source-github' 'specialist':10 'specif':302 'speed':212 'spring':2,6,15,27,37,168,218,252,277,312,640,646,653,661 'spring-boot-starter-test':645 'spring-boot-starter-webmvc-test':652 'spring-boot-test':1 'spring-boot-testcontain':660 'springboottest':121,272 'starter':299,304,648,655 'string':182 'structur':507 'style':71,157,293 'suggest':357 'suit':215 'techniqu':18 'technolog':301 'technology-specif':300 'test':4,9,17,29,36,50,89,124,149,150,197,204,214,225,233,242,254,262,270,297,303,315,330,342,393,407,468,478,481,491,503,508,538,542,551,563,649,650,657,658,664 'testabl':427 'testcontain':144,191,239,663 'testresttempl':285 'tool':60,151 'topic-agent-skills' 'topic-agents' 'topic-awesome' 'topic-custom-agents' 'topic-github-copilot' 'topic-hacktoberfest' 'topic-prompt-engineering' 'track':596 'tradit':162 'tree':224 'understand':556 'unit':52,428 'updateinventori':444 'use':61,458,472,520,588 'user':366,370,384 'valid':413,526,620 'validateord':434 'var':436 'verbos':76 'vip':487 'void':489,501 'web':135,296 'webmvc':656 'webmvctest':97,230 'write':541 'xml':643 'yes':229,236,247,258,265,271","prices":[{"id":"6ce4c0a0-6ac1-4fab-b15b-46381b42f128","listingId":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"github","category":"awesome-copilot","install_from":"skills.sh"},"createdAt":"2026-04-18T20:31:42.661Z"}],"sources":[{"listingId":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","source":"github","sourceId":"github/awesome-copilot/spring-boot-testing","sourceUrl":"https://github.com/github/awesome-copilot/tree/main/skills/spring-boot-testing","isPrimary":false,"firstSeenAt":"2026-04-18T21:51:18.370Z","lastSeenAt":"2026-05-18T18:52:25.669Z"},{"listingId":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","source":"skills_sh","sourceId":"github/awesome-copilot/spring-boot-testing","sourceUrl":"https://skills.sh/github/awesome-copilot/spring-boot-testing","isPrimary":true,"firstSeenAt":"2026-04-18T20:31:42.661Z","lastSeenAt":"2026-05-07T22:40:32.606Z"}],"details":{"listingId":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"github","slug":"spring-boot-testing","github":{"repo":"github/awesome-copilot","stars":33270,"topics":["agent-skills","agents","ai","awesome","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"license":"mit","html_url":"https://github.com/github/awesome-copilot","pushed_at":"2026-05-18T01:26:59Z","description":"Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.","skill_md_sha":"9e97e9835e1ffefcd26f7b46b7633070cd5fd13e","skill_md_path":"skills/spring-boot-testing/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/github/awesome-copilot/tree/main/skills/spring-boot-testing"},"layout":"multi","source":"github","category":"awesome-copilot","frontmatter":{"name":"spring-boot-testing","description":"Expert Spring Boot 4 testing specialist that selects the best Spring Boot testing techniques for your situation with Junit 6 and AssertJ."},"skills_sh_url":"https://skills.sh/github/awesome-copilot/spring-boot-testing"},"updatedAt":"2026-05-18T18:52:25.669Z"}}