{"id":"ddfba497-30df-4fed-8a2e-b6e7ce7863b2","shortId":"9LvuHQ","kind":"skill","title":"Spring Boot Testing","tagline":"Awesome Copilot skill by Github","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"],"capabilities":["skill","source-github","category-awesome-copilot"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/spring-boot-testing","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"install_from":"skills.sh"}},"qualityScore":"0.300","qualityRationale":"deterministic score 0.30 from registry signals: · indexed on skills.sh · published under github/awesome-copilot","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:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T05:40:33.717Z","embedding":null,"createdAt":"2026-04-18T20:31:42.661Z","updatedAt":"2026-04-22T05:40:33.717Z","lastSeenAt":"2026-04-22T05:40:33.717Z","tsv":"'-3.2':147 '-7':323 '1':31,314,494,594 '2':40,336,504,603 '3':51,188,347,512,609 '3.2':141 '4':21,60,152,261,360,615,624 '4.0':202 '5':322 '50':401 '7':296 '80':550,581 'actual':542 'agre':353 'aim':548 'algorithm':605 'altern':69,265,507 'alway':488 'analyz':315 'annot':74 'api':62,91,238,619 'applic':22,102 'applydiscount':422 'array':172 'assert':56,159,276,587 'assertj':52,138,274 'assertj-styl':137,273 'assess':302 'automat':289 'avoid':432 'awesom':4 'balanc':556 'behavior':540 'benefici':564 'best':27,298 'boolean':165 'boot':2,10,20,151,201,260,623,629,636,644 'break':340 'busi':225,596 'business-crit':595 'cach':292 'calcul':397,466,608 'case':325,503,511,544,614 'category-awesome-copilot' 'chang':203 'clarifi':459 'class':307 'client':89,130,154,239 'code':300,342,373,433,539,551 'common':439,501 'comparison':114 'complet':39 'complex':185,301,310,316,335,372,385,604 'concern':405 'condit':517 'confid':50 'config':258 'context':235,257,287,293 'continu':369 'control':76,209 'copilot':5 'core':29 'cover':327 'coverag':486,546,552,562,575,579,582 'creat':435 'createord':420 'credit':482 'critic':597 'custom':470,479 'data':123,180 'databas':620 'datajpatest':85,219 'date':166 'db':223 'de':96 'decid':367 'decis':111,205,349 'depend':158,621 'deprec':271 'descript':455 'despit':376 'difficulti':378 'discount':396,467,607 'display':456 'displaynam':453,464,474 'edg':510,613 'effect':313 'effort':560 'endpoint':210 'enhanc':446 'error':516,610 'etc':178 'exampl':379 'except':612 'exceptions/errors':513 'execut':590 'expert':15 'extern':90,237,618 'extract':358 'failur':518 'fast':35 'fluent':54 'focus':37,345,584 'framework':295 'full':101,250 'function':346 'generat':181,184 'github':8 'give':48 'goal':547,569 'guid':16 'handl':611 'happi':498 'hard':387 'help':356,537 'helper':436 'higher':561 'highlight':262 'http':77 'identifi':357 'implement':374 'input':515 'insuffici':481 'integr':38,251,616 'intent':461 'invalid':514 'inventori':399 'jacoco':571 'java':383,462 'jpa':83 'json':95,245 'jsontest':98,248 'junit':231 'layer':118,124 'legaci':68 'librari':160 'like':333 'line':402 'list':169 'logic':226 'main':495 'maintain':449 'make':532 'map':171,246 'matcher':59 'matrix':112 'maven':572 'meaning':586 'method':305,330,386,437 'migrat':191 'mind':530 'minim':256 'minimum':583 'mix':404 'mock':157,443 'mockbean':270 'mockito':232 'mockitobean':268 'mockmvc':120,140,145 'mockmvctest':64,214,272 'mockrestserviceserv':243 'mode':519 'modern':24,61,264 'modular':280 'mysql':177 'name':457 'narrowest':45 'need':249,319,363 'notif':400 'object':187,441 'order':391,412,419,423,425,427,429,431,477,487,493,601 'orderrequest':393,414 'org.springframework.boot':626,633,641 'organ':451 'path':499,506,598 'pattern':25 'paus':288,290 'payment':398,599 'perform':190 'plain':230 'plugin':573 'point':359,617 'postgresql':176 'practic':28,299,555 'pre':146 'prefer':63 'price':606 'principl':30 'priorit':593 'proceed':361 'process':600 'processord':392,413 'processpay':424 'product':521,527,543 'properti':189 'provid':14 'public':390,411 'pyramid':33 'qualiti':558 'queri':84,217 'quick':204 'readabl':55,447 'real':222,526 'recommend':337,382 'redund':434 'refactor':338,355,381,407 'refer':75,108,134 'references/assertj-basics.md':161,162 'references/assertj-collections.md':167,168 'references/context-caching.md':192,193 'references/datajpatest.md':86,87,121,122 'references/instancio.md':182,183 'references/mockitobean.md':155,156 'references/mockmvc-classic.md':142,143 'references/mockmvc-tester.md':135,136 'references/restclienttest.md':93,94,127,128 'references/resttestclient.md':148,149 'references/sb4-migration.md':198,199 'references/test-slices-overview.md':99,100,104,105,109,110 'references/testcontainers-jdbc.md':174,175 'references/webmvctest.md':80,81,115,116 'reject':476 'relat':535 'replac':269 'report':576 'repositori':82,216 'request':394,415,417,421 'rest':88,129,153 'restclienttest':92,241 'resttestcli':66,263 'return':430 'right':41 'rule':580 'scalar':163 'scenario':73,496,509,522,528 'semant':78 'sendnotif':428 'serial':97 'servic':228 'set':170 'setup':444 'shouldcalculatediscountforvip':472 'shouldrejectorderforinsufficientcredit':484 'singl':329 'skill':6,13 'slice':36,46,72,107 'smaller':344 'source-github' 'specif':284 'speed':194 'spring':1,9,19,150,200,234,259,294,622,628,635,643 'spring-boot-starter-test':627 'spring-boot-starter-webmvc-test':634 'spring-boot-testcontain':642 'springboottest':103,254 'starter':281,286,630,637 'string':164 'structur':489 'style':53,139,275 'suggest':339 'suit':197 'technolog':283 'technology-specif':282 'test':3,11,18,32,71,106,131,132,179,186,196,207,215,224,236,244,252,279,285,297,312,324,375,389,450,460,463,473,485,490,520,524,533,545,631,632,639,640,646 'testabl':409 'testcontain':126,173,221,645 'testresttempl':267 'tool':42,133 'track':578 'tradit':144 'tree':206 'understand':538 'unit':34,410 'updateinventori':426 'use':43,440,454,502,570 'user':348,352,366 'valid':395,508,602 'validateord':416 'var':418 'verbos':58 'vip':469 'void':471,483 'web':117,278 'webmvc':638 'webmvctest':79,212 'write':523 'xml':625 'yes':211,218,229,240,247,253","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-04-22T00:52:17.701Z"},{"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-04-22T05:40:33.717Z"}],"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","source":"skills_sh","category":"awesome-copilot","skills_sh_url":"https://skills.sh/github/awesome-copilot/spring-boot-testing"},"updatedAt":"2026-04-22T05:40:33.717Z"}}