qa-skills 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -0
- package/bin/cli.js +42 -0
- package/dist/agents/registry.d.ts +5 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +101 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +9 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/dependencies.d.ts +21 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +125 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/installer.d.ts +25 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +437 -0
- package/dist/installer.js.map +1 -0
- package/dist/scaffold.d.ts +27 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +182 -0
- package/dist/scaffold.js.map +1 -0
- package/package.json +40 -0
- package/skills/qa-accessibility-test-writer/SKILL.md +127 -0
- package/skills/qa-accessibility-test-writer/references/axe-core-patterns.md +349 -0
- package/skills/qa-accessibility-test-writer/references/best-practices.md +184 -0
- package/skills/qa-accessibility-test-writer/references/wcag-tests.md +331 -0
- package/skills/qa-api-contract-curator/SKILL.md +104 -0
- package/skills/qa-api-contract-curator/references/breaking-changes.md +363 -0
- package/skills/qa-api-contract-curator/references/openapi-structure.md +404 -0
- package/skills/qa-browser-data-collector/SKILL.md +132 -0
- package/skills/qa-browser-data-collector/references/data-collection-checklist.md +91 -0
- package/skills/qa-browser-data-collector/references/playwright-mcp-patterns.md +113 -0
- package/skills/qa-bug-ticket-creator/SKILL.md +148 -0
- package/skills/qa-bug-ticket-creator/references/bug-report-format.md +149 -0
- package/skills/qa-bug-ticket-creator/references/severity-guide.md +81 -0
- package/skills/qa-bug-ticket-creator/templates/bug-ticket-template.md +39 -0
- package/skills/qa-changelog-analyzer/SKILL.md +134 -0
- package/skills/qa-changelog-analyzer/references/git-analysis-patterns.md +138 -0
- package/skills/qa-changelog-analyzer/references/impact-mapping.md +120 -0
- package/skills/qa-clickup-integration/SKILL.md +166 -0
- package/skills/qa-clickup-integration/references/api-patterns.md +102 -0
- package/skills/qa-clickup-integration/references/field-mapping.md +71 -0
- package/skills/qa-codeceptjs-writer/SKILL.md +136 -0
- package/skills/qa-codeceptjs-writer/references/best-practices.md +207 -0
- package/skills/qa-codeceptjs-writer/references/config.md +255 -0
- package/skills/qa-codeceptjs-writer/references/patterns.md +285 -0
- package/skills/qa-coverage-analyzer/SKILL.md +166 -0
- package/skills/qa-coverage-analyzer/references/best-practices.md +142 -0
- package/skills/qa-coverage-analyzer/references/coverage-dimensions.md +155 -0
- package/skills/qa-coverage-analyzer/references/tools.md +204 -0
- package/skills/qa-cypress-writer/SKILL.md +134 -0
- package/skills/qa-cypress-writer/references/assertions.md +121 -0
- package/skills/qa-cypress-writer/references/best-practices.md +82 -0
- package/skills/qa-cypress-writer/references/config.md +121 -0
- package/skills/qa-cypress-writer/references/patterns.md +170 -0
- package/skills/qa-data-factory/SKILL.md +126 -0
- package/skills/qa-data-factory/references/factory-patterns.md +164 -0
- package/skills/qa-data-factory/references/faker-guide.md +131 -0
- package/skills/qa-diagram-generator/SKILL.md +125 -0
- package/skills/qa-diagram-generator/references/c4-model.md +53 -0
- package/skills/qa-diagram-generator/references/charts.md +58 -0
- package/skills/qa-diagram-generator/references/class-diagram.md +85 -0
- package/skills/qa-diagram-generator/references/er-diagram.md +69 -0
- package/skills/qa-diagram-generator/references/flowchart.md +92 -0
- package/skills/qa-diagram-generator/references/from-screenshot.md +45 -0
- package/skills/qa-diagram-generator/references/gantt.md +49 -0
- package/skills/qa-diagram-generator/references/journey.md +50 -0
- package/skills/qa-diagram-generator/references/mindmap.md +75 -0
- package/skills/qa-diagram-generator/references/sequence.md +69 -0
- package/skills/qa-diagram-generator/references/state-diagram.md +56 -0
- package/skills/qa-discovery-interview/SKILL.md +182 -0
- package/skills/qa-discovery-interview/references/completeness-checklist.md +53 -0
- package/skills/qa-discovery-interview/references/conflict-patterns.md +101 -0
- package/skills/qa-discovery-interview/references/qa-categories.md +147 -0
- package/skills/qa-discovery-interview/templates/qa-brief-template.md +168 -0
- package/skills/qa-environment-checker/SKILL.md +142 -0
- package/skills/qa-environment-checker/references/dependency-matrix.md +101 -0
- package/skills/qa-environment-checker/references/health-checks.md +209 -0
- package/skills/qa-environment-checker/templates/env-readiness-template.md +64 -0
- package/skills/qa-flaky-detector/SKILL.md +153 -0
- package/skills/qa-flaky-detector/references/ci-analysis.md +140 -0
- package/skills/qa-flaky-detector/references/flaky-patterns.md +247 -0
- package/skills/qa-github-issues-enhanced/SKILL.md +175 -0
- package/skills/qa-github-issues-enhanced/references/issue-templates.md +425 -0
- package/skills/qa-github-issues-enhanced/references/label-taxonomy.md +130 -0
- package/skills/qa-github-issues-enhanced/references/workflow-patterns.md +188 -0
- package/skills/qa-httpx-writer/SKILL.md +138 -0
- package/skills/qa-httpx-writer/references/assertions.md +195 -0
- package/skills/qa-httpx-writer/references/best-practices.md +140 -0
- package/skills/qa-httpx-writer/references/config.md +212 -0
- package/skills/qa-httpx-writer/references/patterns.md +262 -0
- package/skills/qa-jest-writer/SKILL.md +131 -0
- package/skills/qa-jest-writer/references/assertions.md +125 -0
- package/skills/qa-jest-writer/references/best-practices.md +136 -0
- package/skills/qa-jest-writer/references/config.md +134 -0
- package/skills/qa-jest-writer/references/patterns.md +172 -0
- package/skills/qa-jira-integration/SKILL.md +135 -0
- package/skills/qa-jira-integration/references/api-patterns.md +143 -0
- package/skills/qa-jira-integration/references/field-mapping.md +79 -0
- package/skills/qa-jira-integration/references/xray-integration.md +85 -0
- package/skills/qa-jmeter-writer/SKILL.md +171 -0
- package/skills/qa-jmeter-writer/references/best-practices.md +157 -0
- package/skills/qa-jmeter-writer/references/config.md +204 -0
- package/skills/qa-jmeter-writer/references/patterns.md +242 -0
- package/skills/qa-junit5-writer/SKILL.md +157 -0
- package/skills/qa-junit5-writer/references/assertions.md +118 -0
- package/skills/qa-junit5-writer/references/config.md +97 -0
- package/skills/qa-junit5-writer/references/patterns.md +162 -0
- package/skills/qa-k6-writer/SKILL.md +155 -0
- package/skills/qa-k6-writer/references/best-practices.md +236 -0
- package/skills/qa-k6-writer/references/config.md +219 -0
- package/skills/qa-k6-writer/references/patterns.md +304 -0
- package/skills/qa-linear-integration/SKILL.md +137 -0
- package/skills/qa-linear-integration/references/api-patterns.md +249 -0
- package/skills/qa-linear-integration/references/field-mapping.md +121 -0
- package/skills/qa-locust-writer/SKILL.md +151 -0
- package/skills/qa-locust-writer/references/best-practices.md +126 -0
- package/skills/qa-locust-writer/references/config.md +170 -0
- package/skills/qa-locust-writer/references/patterns.md +235 -0
- package/skills/qa-manual-test-designer/SKILL.md +145 -0
- package/skills/qa-manual-test-designer/references/exploratory-charters.md +138 -0
- package/skills/qa-manual-test-designer/references/personas.md +146 -0
- package/skills/qa-manual-test-designer/templates/exploratory-charter-template.md +47 -0
- package/skills/qa-manual-test-designer/templates/test-case-template.md +31 -0
- package/skills/qa-mobile-test-writer/SKILL.md +144 -0
- package/skills/qa-mobile-test-writer/references/best-practices.md +214 -0
- package/skills/qa-mobile-test-writer/references/config.md +309 -0
- package/skills/qa-mobile-test-writer/references/patterns.md +304 -0
- package/skills/qa-nfr-analyst/SKILL.md +177 -0
- package/skills/qa-nfr-analyst/references/iso-25010-model.md +159 -0
- package/skills/qa-nfr-analyst/references/owasp-wstg-baseline.md +202 -0
- package/skills/qa-nfr-analyst/references/wcag-checklist.md +184 -0
- package/skills/qa-nfr-analyst/templates/owasp-checklist-template.md +89 -0
- package/skills/qa-nfr-analyst/templates/wcag-checklist-template.md +48 -0
- package/skills/qa-orchestrator/SKILL.md +132 -0
- package/skills/qa-orchestrator/references/handoff-chains.md +105 -0
- package/skills/qa-orchestrator/references/pipeline-modes.md +115 -0
- package/skills/qa-orchestrator/references/scheduler-rules.md +84 -0
- package/skills/qa-pact-writer/SKILL.md +133 -0
- package/skills/qa-pact-writer/references/best-practices.md +100 -0
- package/skills/qa-pact-writer/references/config.md +135 -0
- package/skills/qa-pact-writer/references/patterns.md +161 -0
- package/skills/qa-plan-creator/SKILL.md +139 -0
- package/skills/qa-plan-creator/references/introduction-plan.md +43 -0
- package/skills/qa-plan-creator/references/migration-plan.md +44 -0
- package/skills/qa-plan-creator/references/onboarding-plan.md +46 -0
- package/skills/qa-plan-creator/references/performance-plan.md +44 -0
- package/skills/qa-plan-creator/references/regression-plan.md +45 -0
- package/skills/qa-plan-creator/references/release-plan.md +45 -0
- package/skills/qa-plan-creator/references/sprint-plan.md +44 -0
- package/skills/qa-plan-creator/references/test-plan.md +59 -0
- package/skills/qa-plan-creator/references/uat-plan.md +43 -0
- package/skills/qa-plan-creator/templates/checklist-template.md +36 -0
- package/skills/qa-plan-creator/templates/regression-checklist-template.md +49 -0
- package/skills/qa-plan-creator/templates/release-checklist-template.md +46 -0
- package/skills/qa-plan-creator/templates/test-plan-template.md +74 -0
- package/skills/qa-playwright-py-writer/SKILL.md +156 -0
- package/skills/qa-playwright-py-writer/references/best-practices.md +194 -0
- package/skills/qa-playwright-py-writer/references/config.md +195 -0
- package/skills/qa-playwright-py-writer/references/patterns.md +212 -0
- package/skills/qa-playwright-ts-writer/SKILL.md +151 -0
- package/skills/qa-playwright-ts-writer/references/assertions.md +109 -0
- package/skills/qa-playwright-ts-writer/references/best-practices.md +191 -0
- package/skills/qa-playwright-ts-writer/references/config.md +144 -0
- package/skills/qa-playwright-ts-writer/references/patterns.md +171 -0
- package/skills/qa-pytest-writer/SKILL.md +145 -0
- package/skills/qa-pytest-writer/references/assertions.md +149 -0
- package/skills/qa-pytest-writer/references/best-practices.md +97 -0
- package/skills/qa-pytest-writer/references/config.md +176 -0
- package/skills/qa-pytest-writer/references/patterns.md +251 -0
- package/skills/qa-qase-integration/SKILL.md +149 -0
- package/skills/qa-qase-integration/references/api-reference.md +354 -0
- package/skills/qa-qase-integration/references/ci-integration.md +196 -0
- package/skills/qa-qase-integration/references/field-mapping.md +157 -0
- package/skills/qa-requirements-generator/SKILL.md +152 -0
- package/skills/qa-requirements-generator/references/iso-29148-structure.md +153 -0
- package/skills/qa-requirements-generator/references/requirement-patterns.md +278 -0
- package/skills/qa-rest-assured-writer/SKILL.md +137 -0
- package/skills/qa-rest-assured-writer/references/best-practices.md +50 -0
- package/skills/qa-rest-assured-writer/references/config.md +124 -0
- package/skills/qa-rest-assured-writer/references/patterns.md +192 -0
- package/skills/qa-risk-analyzer/SKILL.md +158 -0
- package/skills/qa-risk-analyzer/references/impact-analysis.md +133 -0
- package/skills/qa-risk-analyzer/references/risk-factors.md +123 -0
- package/skills/qa-robot-framework-writer/SKILL.md +147 -0
- package/skills/qa-robot-framework-writer/references/best-practices.md +249 -0
- package/skills/qa-robot-framework-writer/references/config.md +204 -0
- package/skills/qa-robot-framework-writer/references/libraries.md +273 -0
- package/skills/qa-robot-framework-writer/references/patterns.md +216 -0
- package/skills/qa-security-test-writer/SKILL.md +123 -0
- package/skills/qa-security-test-writer/references/best-practices.md +155 -0
- package/skills/qa-security-test-writer/references/owasp-top10.md +331 -0
- package/skills/qa-security-test-writer/references/zap-config.md +258 -0
- package/skills/qa-selenium-java-writer/SKILL.md +143 -0
- package/skills/qa-selenium-java-writer/references/best-practices.md +59 -0
- package/skills/qa-selenium-java-writer/references/config.md +143 -0
- package/skills/qa-selenium-java-writer/references/patterns.md +170 -0
- package/skills/qa-selenium-py-writer/SKILL.md +150 -0
- package/skills/qa-selenium-py-writer/references/best-practices.md +175 -0
- package/skills/qa-selenium-py-writer/references/config.md +224 -0
- package/skills/qa-selenium-py-writer/references/patterns.md +255 -0
- package/skills/qa-shortcut-integration/SKILL.md +143 -0
- package/skills/qa-shortcut-integration/references/api-patterns.md +126 -0
- package/skills/qa-shortcut-integration/references/field-mapping.md +66 -0
- package/skills/qa-spec-auditor/SKILL.md +162 -0
- package/skills/qa-spec-auditor/references/audit-checklist.md +144 -0
- package/skills/qa-spec-auditor/references/drift-patterns.md +207 -0
- package/skills/qa-spec-writer/SKILL.md +143 -0
- package/skills/qa-spec-writer/references/gherkin-guide.md +253 -0
- package/skills/qa-spec-writer/references/specification-patterns.md +274 -0
- package/skills/qa-spring-test-writer/SKILL.md +170 -0
- package/skills/qa-spring-test-writer/references/best-practices.md +57 -0
- package/skills/qa-spring-test-writer/references/config.md +179 -0
- package/skills/qa-spring-test-writer/references/patterns.md +235 -0
- package/skills/qa-supertest-writer/SKILL.md +150 -0
- package/skills/qa-supertest-writer/references/assertions.md +192 -0
- package/skills/qa-supertest-writer/references/best-practices.md +102 -0
- package/skills/qa-supertest-writer/references/config.md +166 -0
- package/skills/qa-supertest-writer/references/patterns.md +242 -0
- package/skills/qa-task-creator/SKILL.md +142 -0
- package/skills/qa-task-creator/references/linking-patterns.md +127 -0
- package/skills/qa-task-creator/references/task-types.md +169 -0
- package/skills/qa-task-creator/templates/task-template.md +24 -0
- package/skills/qa-test-doc-compiler/SKILL.md +114 -0
- package/skills/qa-test-doc-compiler/references/agile-tailoring.md +220 -0
- package/skills/qa-test-doc-compiler/references/iso-29119-3-documents.md +302 -0
- package/skills/qa-test-healer/SKILL.md +101 -0
- package/skills/qa-test-healer/references/diagnosis-patterns.md +142 -0
- package/skills/qa-test-healer/references/fix-strategies.md +177 -0
- package/skills/qa-test-reporter/SKILL.md +130 -0
- package/skills/qa-test-reporter/references/best-practices.md +162 -0
- package/skills/qa-test-reporter/references/iso-29119-reports.md +236 -0
- package/skills/qa-test-reporter/references/report-formats.md +287 -0
- package/skills/qa-test-reviewer/SKILL.md +142 -0
- package/skills/qa-test-reviewer/references/anti-patterns.md +268 -0
- package/skills/qa-test-reviewer/references/review-checklist.md +93 -0
- package/skills/qa-test-strategy/SKILL.md +133 -0
- package/skills/qa-test-strategy/references/entry-exit-criteria.md +176 -0
- package/skills/qa-test-strategy/references/risk-matrix.md +102 -0
- package/skills/qa-test-strategy/references/testing-types.md +143 -0
- package/skills/qa-testcase-from-docs/SKILL.md +161 -0
- package/skills/qa-testcase-from-docs/references/test-case-format.md +196 -0
- package/skills/qa-testcase-from-docs/references/test-design-techniques.md +126 -0
- package/skills/qa-testcase-from-docs/templates/test-case-template.md +31 -0
- package/skills/qa-testcase-from-ui/SKILL.md +109 -0
- package/skills/qa-testcase-from-ui/references/ui-element-patterns.md +126 -0
- package/skills/qa-testcase-from-ui/references/visual-analysis-guide.md +146 -0
- package/skills/qa-testcase-from-ui/templates/test-case-template.md +31 -0
- package/skills/qa-visual-regression-writer/SKILL.md +175 -0
- package/skills/qa-visual-regression-writer/references/best-practices.md +154 -0
- package/skills/qa-visual-regression-writer/references/config.md +220 -0
- package/skills/qa-visual-regression-writer/references/patterns.md +213 -0
- package/skills/qa-vitest-writer/SKILL.md +141 -0
- package/skills/qa-vitest-writer/references/assertions.md +105 -0
- package/skills/qa-vitest-writer/references/best-practices.md +62 -0
- package/skills/qa-vitest-writer/references/config.md +127 -0
- package/skills/qa-vitest-writer/references/patterns.md +141 -0
- package/skills/qa-webdriverio-writer/SKILL.md +145 -0
- package/skills/qa-webdriverio-writer/references/best-practices.md +176 -0
- package/skills/qa-webdriverio-writer/references/config.md +240 -0
- package/skills/qa-webdriverio-writer/references/patterns.md +269 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa-spring-test-writer
|
|
3
|
+
description: Generate Spring Boot integration tests with @SpringBootTest, MockMvc, TestContainers, @DataJpaTest, WebTestClient, and profile-based configuration.
|
|
4
|
+
output_dir: tests/integration
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QA Spring Test Writer
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Write Spring Boot integration tests from test case specifications. Transform structured test cases into executable Spring test files with @SpringBootTest, MockMvc for REST controller testing, TestContainers for database integration, @DataJpaTest for repository testing, and WebTestClient for WebFlux.
|
|
12
|
+
|
|
13
|
+
## Trigger Phrases
|
|
14
|
+
|
|
15
|
+
- "Write Spring Boot integration tests for [feature]"
|
|
16
|
+
- "Generate MockMvc tests for [controller]"
|
|
17
|
+
- "Create TestContainers tests for [entity/repository]"
|
|
18
|
+
- "Add @DataJpaTest for [repository]"
|
|
19
|
+
- "Spring Boot integration tests with MockMvc"
|
|
20
|
+
- "WebTestClient tests for WebFlux [endpoint]"
|
|
21
|
+
- "Spring integration tests with TestContainers"
|
|
22
|
+
- "MockMvc tests with @MockBean"
|
|
23
|
+
|
|
24
|
+
## Key Features
|
|
25
|
+
|
|
26
|
+
| Feature | Description |
|
|
27
|
+
| ------- | ----------- |
|
|
28
|
+
| **@SpringBootTest** | Full application context; webEnvironment for servlet/reactive |
|
|
29
|
+
| **MockMvc** | REST controller testing without HTTP; perform(get/post).andExpect |
|
|
30
|
+
| **TestContainers** | @Container + PostgreSQLContainer, MySQLContainer for real DB |
|
|
31
|
+
| **@DataJpaTest** | Slice test for JPA repositories; in-memory or TestContainer DB |
|
|
32
|
+
| **WebTestClient** | WebFlux controller testing; bindToController or full server |
|
|
33
|
+
| **@MockBean** | Mock service dependencies in integration tests |
|
|
34
|
+
| **@TestPropertySource** | Override properties; use test profile |
|
|
35
|
+
| **@Transactional** | Rollback after each test for data cleanup |
|
|
36
|
+
|
|
37
|
+
## Workflow
|
|
38
|
+
|
|
39
|
+
1. **Read test cases** — From specs, requirements, or API contracts
|
|
40
|
+
2. **Analyze Java code** — Inspect controllers, services, repositories
|
|
41
|
+
3. **Choose test type** — MockMvc (controller), @DataJpaTest (repository), full @SpringBootTest (integration)
|
|
42
|
+
4. **Generate tests** — Produce `{Feature}IntegrationTest.java`
|
|
43
|
+
5. **Configure TestContainers** — Add @Container for DB when needed
|
|
44
|
+
6. **Run** — User runs `mvn test` or `./gradlew test`
|
|
45
|
+
|
|
46
|
+
## Key Patterns
|
|
47
|
+
|
|
48
|
+
| Pattern | Usage |
|
|
49
|
+
| ------- | ----- |
|
|
50
|
+
| `mockMvc.perform(get("/api/users")).andExpect(status().isOk())` | MockMvc GET |
|
|
51
|
+
| `mockMvc.perform(post("/api/users").contentType(JSON).content(body)).andExpect(status().isCreated())` | MockMvc POST |
|
|
52
|
+
| `jsonPath("$.id").value(1)` | JSON path assertion |
|
|
53
|
+
| `@Container static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")` | TestContainers DB |
|
|
54
|
+
| `@DataJpaTest` | Repository slice test |
|
|
55
|
+
| `repository.save(entity); assertEquals(1, repository.findAll().size())` | Repository assertions |
|
|
56
|
+
| `webTestClient.get().uri("/api/users").exchange().expectStatus().isOk()` | WebTestClient |
|
|
57
|
+
| `@MockBean UserService userService` | Mock service in context |
|
|
58
|
+
|
|
59
|
+
## MockMvc Patterns
|
|
60
|
+
|
|
61
|
+
```java
|
|
62
|
+
@SpringBootTest
|
|
63
|
+
@AutoConfigureMockMvc
|
|
64
|
+
class UserControllerIntegrationTest {
|
|
65
|
+
@Autowired MockMvc mockMvc;
|
|
66
|
+
|
|
67
|
+
@Test
|
|
68
|
+
void getUsers_returnsOk() throws Exception {
|
|
69
|
+
mockMvc.perform(get("/api/users"))
|
|
70
|
+
.andExpect(status().isOk())
|
|
71
|
+
.andExpect(jsonPath("$").isArray());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@Test
|
|
75
|
+
void createUser_returnsCreated() throws Exception {
|
|
76
|
+
String body = "{\"name\":\"John\",\"email\":\"john@example.com\"}";
|
|
77
|
+
mockMvc.perform(post("/api/users")
|
|
78
|
+
.contentType(MediaType.APPLICATION_JSON)
|
|
79
|
+
.content(body))
|
|
80
|
+
.andExpect(status().isCreated())
|
|
81
|
+
.andExpect(jsonPath("$.id").exists());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## TestContainers + @DataJpaTest
|
|
87
|
+
|
|
88
|
+
```java
|
|
89
|
+
@DataJpaTest
|
|
90
|
+
@Testcontainers
|
|
91
|
+
class UserRepositoryIntegrationTest {
|
|
92
|
+
@Container
|
|
93
|
+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
|
|
94
|
+
|
|
95
|
+
@DynamicPropertySource
|
|
96
|
+
static void configureProperties(DynamicPropertyRegistry registry) {
|
|
97
|
+
registry.add("spring.datasource.url", postgres::getJdbcUrl);
|
|
98
|
+
registry.add("spring.datasource.username", postgres::getUsername);
|
|
99
|
+
registry.add("spring.datasource.password", postgres::getPassword);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Autowired UserRepository repository;
|
|
103
|
+
|
|
104
|
+
@Test
|
|
105
|
+
void save_findsById() {
|
|
106
|
+
User user = new User("John", "john@example.com");
|
|
107
|
+
User saved = repository.save(user);
|
|
108
|
+
assertThat(repository.findById(saved.getId())).isPresent();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## File Naming
|
|
114
|
+
|
|
115
|
+
- `{Feature}IntegrationTest.java` — Integration test classes (e.g., `UserControllerIntegrationTest.java`, `OrderRepositoryIntegrationTest.java`)
|
|
116
|
+
- Place in `src/test/java` per Maven/Gradle convention
|
|
117
|
+
|
|
118
|
+
## Scope
|
|
119
|
+
|
|
120
|
+
**Can do (autonomous):**
|
|
121
|
+
- Generate Spring Boot integration tests from test case specs
|
|
122
|
+
- Use MockMvc for REST controller testing
|
|
123
|
+
- Use TestContainers for database integration tests
|
|
124
|
+
- Use @DataJpaTest for repository slice tests
|
|
125
|
+
- Use WebTestClient for WebFlux controller testing
|
|
126
|
+
- Apply @MockBean for service mocking
|
|
127
|
+
- Use @TestPropertySource and profiles for configuration
|
|
128
|
+
- Use @Transactional for test data cleanup
|
|
129
|
+
|
|
130
|
+
**Cannot do (requires confirmation):**
|
|
131
|
+
- Change production code structure
|
|
132
|
+
- Add dependencies not in pom.xml/build.gradle
|
|
133
|
+
- Override project Spring config without approval
|
|
134
|
+
- Modify database schema
|
|
135
|
+
|
|
136
|
+
**Will not do (out of scope):**
|
|
137
|
+
- Execute tests (user runs `mvn test`)
|
|
138
|
+
- Write unit tests without Spring (use qa-junit5-writer)
|
|
139
|
+
- Modify CI/CD pipelines
|
|
140
|
+
- Bypass security or access restricted areas
|
|
141
|
+
|
|
142
|
+
## References
|
|
143
|
+
|
|
144
|
+
- `references/patterns.md` — MockMvc, TestContainers, DataJpaTest, WebTestClient
|
|
145
|
+
- `references/config.md` — Spring Boot test config, profiles, TestContainers setup
|
|
146
|
+
- `references/best-practices.md` — Spring integration testing best practices
|
|
147
|
+
|
|
148
|
+
## Quality Checklist
|
|
149
|
+
|
|
150
|
+
- [ ] Appropriate test slice (@SpringBootTest, @DataJpaTest) for scope
|
|
151
|
+
- [ ] MockMvc/WebTestClient used for controller tests; avoid full HTTP when possible
|
|
152
|
+
- [ ] TestContainers for real DB when repository/DB behavior matters
|
|
153
|
+
- [ ] @Transactional or @DirtiesContext for data isolation where needed
|
|
154
|
+
- [ ] @MockBean only for external dependencies; avoid over-mocking
|
|
155
|
+
- [ ] @TestPropertySource for test-specific config
|
|
156
|
+
- [ ] Tests independent (no shared mutable state)
|
|
157
|
+
- [ ] Traceability to test case IDs where applicable
|
|
158
|
+
- [ ] No hardcoded secrets (use @TestPropertySource or env)
|
|
159
|
+
- [ ] File naming follows `{Feature}IntegrationTest.java` convention
|
|
160
|
+
|
|
161
|
+
## Troubleshooting
|
|
162
|
+
|
|
163
|
+
| Symptom | Likely Cause | Fix |
|
|
164
|
+
| ------- | ------------ | --- |
|
|
165
|
+
| Context fails to load | Missing bean, circular dependency | Use @MockBean for problematic deps; check @ComponentScan |
|
|
166
|
+
| MockMvc 404 | Wrong path, context path | Verify @RequestMapping paths; check base path |
|
|
167
|
+
| TestContainers timeout | Image pull slow, resource limits | Use cached image; increase timeout; check Docker |
|
|
168
|
+
| @DataJpaTest fails | Missing JPA config, wrong DB | Add @EntityScan if needed; configure TestContainers |
|
|
169
|
+
| Flaky tests | Shared state, order-dependent | Use @Transactional; ensure test isolation |
|
|
170
|
+
| WebTestClient fails | Wrong binding | Use bindToController or bindToServer; check WebFlux config |
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Spring Integration Testing Best Practices
|
|
2
|
+
|
|
3
|
+
## Test Slice Selection
|
|
4
|
+
|
|
5
|
+
| Slice | Use When | Avoid When |
|
|
6
|
+
| ----- | -------- | ---------- |
|
|
7
|
+
| @SpringBootTest | Full integration, multiple layers | Unit testing; slow feedback |
|
|
8
|
+
| @WebMvcTest | Controller-only, mock services | Need real DB, security context |
|
|
9
|
+
| @DataJpaTest | Repository behavior, queries | Need full app, controllers |
|
|
10
|
+
| @JsonTest | JSON serialization | General integration |
|
|
11
|
+
| @RestClientTest | RestTemplate/WebClient | Full HTTP integration |
|
|
12
|
+
|
|
13
|
+
## MockMvc Best Practices
|
|
14
|
+
|
|
15
|
+
1. **Prefer MockMvc over real HTTP** — Faster, no network; use RestTemplate/WebClient only when needed
|
|
16
|
+
2. **Use ObjectMapper for JSON** — Avoid hand-crafted JSON strings
|
|
17
|
+
3. **Assert status and body** — Always verify status and key response fields
|
|
18
|
+
4. **Use @WithMockUser** — Test security without full auth flow
|
|
19
|
+
5. **Extract common setup** — @BeforeEach for shared request builders
|
|
20
|
+
|
|
21
|
+
## TestContainers Best Practices
|
|
22
|
+
|
|
23
|
+
1. **Use specific image tags** — `postgres:15` not `postgres:latest` for reproducibility
|
|
24
|
+
2. **Reuse containers** — Enable reuse for faster runs when safe
|
|
25
|
+
3. **@DynamicPropertySource** — Prefer over application-test.yml for TestContainers URLs
|
|
26
|
+
4. **One DB per test class** — Avoid shared mutable state; use @Container static
|
|
27
|
+
5. **Consider Testcontainers Cloud** — For CI with limited Docker resources
|
|
28
|
+
|
|
29
|
+
## Data Isolation
|
|
30
|
+
|
|
31
|
+
1. **@Transactional** — Rollback after each test; no manual cleanup
|
|
32
|
+
2. **@DirtiesContext** — Use sparingly when context must be refreshed
|
|
33
|
+
3. **@Sql** — Load test data from scripts when needed
|
|
34
|
+
4. **Avoid @Transactional with @DataJpaTest** — Default rollback; explicit only when testing commit behavior
|
|
35
|
+
|
|
36
|
+
## Performance
|
|
37
|
+
|
|
38
|
+
1. **Minimize @SpringBootTest** — Use slices (@WebMvcTest, @DataJpaTest) when possible
|
|
39
|
+
2. **Lazy context** — Use @MockBean to avoid loading heavy beans
|
|
40
|
+
3. **Parallel execution** — Surefire forkCount; ensure tests are isolated
|
|
41
|
+
4. **Cache context** — Same configuration = cached context across test classes
|
|
42
|
+
|
|
43
|
+
## Security Testing
|
|
44
|
+
|
|
45
|
+
1. **@WithMockUser** — Simulate authenticated user
|
|
46
|
+
2. **@WithAnonymousUser** — Test unauthenticated access
|
|
47
|
+
3. **@WithUserDetails** — Load user from UserDetailsService
|
|
48
|
+
4. **Custom SecurityContext** — For complex scenarios
|
|
49
|
+
|
|
50
|
+
## Common Pitfalls
|
|
51
|
+
|
|
52
|
+
| Pitfall | Fix |
|
|
53
|
+
| ------- | --- |
|
|
54
|
+
| Context loads too much | Use @WebMvcTest or @DataJpaTest; @MockBean external deps |
|
|
55
|
+
| Flaky tests | Ensure @Transactional or proper cleanup; no static mutable state |
|
|
56
|
+
| Slow tests | Use slices; reuse TestContainers; avoid full @SpringBootTest |
|
|
57
|
+
| TestContainers fails in CI | Check Docker availability; use ryuk disabled only for debugging |
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Spring Boot Test Configuration
|
|
2
|
+
|
|
3
|
+
## Maven Dependencies
|
|
4
|
+
|
|
5
|
+
```xml
|
|
6
|
+
<dependencies>
|
|
7
|
+
<dependency>
|
|
8
|
+
<groupId>org.springframework.boot</groupId>
|
|
9
|
+
<artifactId>spring-boot-starter-test</artifactId>
|
|
10
|
+
<scope>test</scope>
|
|
11
|
+
</dependency>
|
|
12
|
+
<dependency>
|
|
13
|
+
<groupId>org.testcontainers</groupId>
|
|
14
|
+
<artifactId>testcontainers</artifactId>
|
|
15
|
+
<scope>test</scope>
|
|
16
|
+
</dependency>
|
|
17
|
+
<dependency>
|
|
18
|
+
<groupId>org.testcontainers</groupId>
|
|
19
|
+
<artifactId>postgresql</artifactId>
|
|
20
|
+
<scope>test</scope>
|
|
21
|
+
</dependency>
|
|
22
|
+
<dependency>
|
|
23
|
+
<groupId>org.testcontainers</groupId>
|
|
24
|
+
<artifactId>junit-jupiter</artifactId>
|
|
25
|
+
<scope>test</scope>
|
|
26
|
+
</dependency>
|
|
27
|
+
</dependencies>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Gradle Dependencies
|
|
31
|
+
|
|
32
|
+
```groovy
|
|
33
|
+
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
34
|
+
testImplementation 'org.testcontainers:testcontainers'
|
|
35
|
+
testImplementation 'org.testcontainers:postgresql'
|
|
36
|
+
testImplementation 'org.testcontainers:junit-jupiter'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## @SpringBootTest Options
|
|
40
|
+
|
|
41
|
+
| Option | Values | Use Case |
|
|
42
|
+
| ------ | ------ | -------- |
|
|
43
|
+
| webEnvironment | NONE, MOCK, RANDOM_PORT, DEFINED_PORT | MOCK for no server; RANDOM_PORT for full integration |
|
|
44
|
+
| classes | Application class | Limit context to specific classes |
|
|
45
|
+
| properties | Key-value pairs | Override properties |
|
|
46
|
+
|
|
47
|
+
```java
|
|
48
|
+
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
|
49
|
+
class FullIntegrationTest { }
|
|
50
|
+
|
|
51
|
+
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
|
52
|
+
@AutoConfigureMockMvc
|
|
53
|
+
class MockMvcTest { }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Test Profiles
|
|
57
|
+
|
|
58
|
+
### application-test.yml
|
|
59
|
+
```yaml
|
|
60
|
+
spring:
|
|
61
|
+
datasource:
|
|
62
|
+
url: jdbc:h2:mem:testdb
|
|
63
|
+
driver-class-name: org.h2.Driver
|
|
64
|
+
jpa:
|
|
65
|
+
hibernate:
|
|
66
|
+
ddl-auto: create-drop
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Activate in Test
|
|
70
|
+
```java
|
|
71
|
+
@SpringBootTest
|
|
72
|
+
@ActiveProfiles("test")
|
|
73
|
+
class ProfileIntegrationTest { }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## TestContainers Setup
|
|
77
|
+
|
|
78
|
+
### JUnit 5 Integration
|
|
79
|
+
```java
|
|
80
|
+
@Testcontainers
|
|
81
|
+
class MyTest {
|
|
82
|
+
@Container
|
|
83
|
+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Shared Container (Singleton)
|
|
88
|
+
```java
|
|
89
|
+
@Testcontainers
|
|
90
|
+
class MyTest {
|
|
91
|
+
@Container
|
|
92
|
+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
|
|
93
|
+
.withReuse(true); // Reuse across test classes (requires testcontainers.reuse.enable=true)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Dynamic Properties
|
|
98
|
+
```java
|
|
99
|
+
@DynamicPropertySource
|
|
100
|
+
static void configureProperties(DynamicPropertyRegistry registry) {
|
|
101
|
+
registry.add("spring.datasource.url", postgres::getJdbcUrl);
|
|
102
|
+
registry.add("spring.datasource.username", postgres::getUsername);
|
|
103
|
+
registry.add("spring.datasource.password", postgres::getPassword);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## MockMvc Configuration
|
|
108
|
+
|
|
109
|
+
### Auto-configure (default with @SpringBootTest webEnvironment=MOCK)
|
|
110
|
+
```java
|
|
111
|
+
@SpringBootTest
|
|
112
|
+
@AutoConfigureMockMvc
|
|
113
|
+
class ControllerTest {
|
|
114
|
+
@Autowired MockMvc mockMvc;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Custom Configuration
|
|
119
|
+
```java
|
|
120
|
+
@Autowired
|
|
121
|
+
void setMockMvc(MockMvcBuilder builder) {
|
|
122
|
+
mockMvc = builder
|
|
123
|
+
.apply(SecurityMockMvcConfigurers.springSecurity())
|
|
124
|
+
.build();
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## WebTestClient Configuration
|
|
129
|
+
|
|
130
|
+
### With RANDOM_PORT
|
|
131
|
+
```java
|
|
132
|
+
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
|
133
|
+
class WebFluxTest {
|
|
134
|
+
@Autowired WebTestClient webTestClient;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### With MockMvc (Servlet)
|
|
139
|
+
```java
|
|
140
|
+
@SpringBootTest
|
|
141
|
+
@AutoConfigureMockMvc
|
|
142
|
+
class WebTestClientTest {
|
|
143
|
+
@Autowired MockMvc mockMvc;
|
|
144
|
+
WebTestClient webTestClient;
|
|
145
|
+
|
|
146
|
+
@BeforeEach
|
|
147
|
+
void setUp() {
|
|
148
|
+
webTestClient = WebTestClient.bindTo(
|
|
149
|
+
MockMvcWebClientBuilder.mockMvcSetup(mockMvc).build()
|
|
150
|
+
).build();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Surefire Configuration (Maven)
|
|
156
|
+
|
|
157
|
+
```xml
|
|
158
|
+
<plugin>
|
|
159
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
160
|
+
<artifactId>maven-surefire-plugin</artifactId>
|
|
161
|
+
<configuration>
|
|
162
|
+
<includes>
|
|
163
|
+
<include>**/*Test.java</include>
|
|
164
|
+
<include>**/*IntegrationTest.java</include>
|
|
165
|
+
</includes>
|
|
166
|
+
<excludes>
|
|
167
|
+
<exclude>**/Abstract*.java</exclude>
|
|
168
|
+
</excludes>
|
|
169
|
+
</configuration>
|
|
170
|
+
</plugin>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Testcontainers Properties
|
|
174
|
+
|
|
175
|
+
### ~/.testcontainers.properties (optional)
|
|
176
|
+
```
|
|
177
|
+
docker.client.strategy=org.testcontainers.dockerclient.UnixSocketClientProviderStrategy
|
|
178
|
+
testcontainers.reuse.enable=true
|
|
179
|
+
```
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Spring Test Patterns
|
|
2
|
+
|
|
3
|
+
## MockMvc Patterns
|
|
4
|
+
|
|
5
|
+
### Basic GET
|
|
6
|
+
```java
|
|
7
|
+
mockMvc.perform(get("/api/users"))
|
|
8
|
+
.andExpect(status().isOk())
|
|
9
|
+
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
|
10
|
+
.andExpect(jsonPath("$").isArray());
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### POST with JSON Body
|
|
14
|
+
```java
|
|
15
|
+
String body = objectMapper.writeValueAsString(new UserRequest("John", "john@example.com"));
|
|
16
|
+
mockMvc.perform(post("/api/users")
|
|
17
|
+
.contentType(MediaType.APPLICATION_JSON)
|
|
18
|
+
.content(body))
|
|
19
|
+
.andExpect(status().isCreated())
|
|
20
|
+
.andExpect(jsonPath("$.id").exists())
|
|
21
|
+
.andExpect(jsonPath("$.name").value("John"));
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### PUT / PATCH / DELETE
|
|
25
|
+
```java
|
|
26
|
+
mockMvc.perform(put("/api/users/1").contentType(JSON).content(body))
|
|
27
|
+
.andExpect(status().isOk());
|
|
28
|
+
|
|
29
|
+
mockMvc.perform(delete("/api/users/1"))
|
|
30
|
+
.andExpect(status().isNoContent());
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Headers and Authentication
|
|
34
|
+
```java
|
|
35
|
+
mockMvc.perform(get("/api/users")
|
|
36
|
+
.header("Authorization", "Bearer " + token)
|
|
37
|
+
.header("X-Request-ID", "req-123"))
|
|
38
|
+
.andExpect(status().isOk());
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### With Security (MockMvc + Spring Security)
|
|
42
|
+
```java
|
|
43
|
+
@WithMockUser(roles = "ADMIN")
|
|
44
|
+
@Test
|
|
45
|
+
void getUsers_asAdmin_returnsOk() throws Exception {
|
|
46
|
+
mockMvc.perform(get("/api/users")).andExpect(status().isOk());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@WithMockUser(username = "user", roles = "USER")
|
|
50
|
+
@Test
|
|
51
|
+
void getUsers_asUser_returnsForbidden() throws Exception {
|
|
52
|
+
mockMvc.perform(get("/api/admin/users")).andExpect(status().isForbidden());
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### JsonPath Assertions
|
|
57
|
+
```java
|
|
58
|
+
.andExpect(jsonPath("$.id").value(1))
|
|
59
|
+
.andExpect(jsonPath("$.name").value("John"))
|
|
60
|
+
.andExpect(jsonPath("$.items[0].name").value("Item1"))
|
|
61
|
+
.andExpect(jsonPath("$.items", hasSize(2)))
|
|
62
|
+
.andExpect(jsonPath("$.active").value(true))
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## TestContainers Patterns
|
|
66
|
+
|
|
67
|
+
### PostgreSQL
|
|
68
|
+
```java
|
|
69
|
+
@Container
|
|
70
|
+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
|
|
71
|
+
.withDatabaseName("testdb")
|
|
72
|
+
.withUsername("test")
|
|
73
|
+
.withPassword("test");
|
|
74
|
+
|
|
75
|
+
@DynamicPropertySource
|
|
76
|
+
static void configureProperties(DynamicPropertyRegistry registry) {
|
|
77
|
+
registry.add("spring.datasource.url", postgres::getJdbcUrl);
|
|
78
|
+
registry.add("spring.datasource.username", postgres::getUsername);
|
|
79
|
+
registry.add("spring.datasource.password", postgres::getPassword);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### MySQL
|
|
84
|
+
```java
|
|
85
|
+
@Container
|
|
86
|
+
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8")
|
|
87
|
+
.withDatabaseName("testdb")
|
|
88
|
+
.withUsername("test")
|
|
89
|
+
.withPassword("test");
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Redis
|
|
93
|
+
```java
|
|
94
|
+
@Container
|
|
95
|
+
static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
|
|
96
|
+
.withExposedPorts(6379);
|
|
97
|
+
|
|
98
|
+
@DynamicPropertySource
|
|
99
|
+
static void configureRedis(DynamicPropertyRegistry registry) {
|
|
100
|
+
registry.add("spring.data.redis.host", redis::getHost);
|
|
101
|
+
registry.add("spring.data.redis.port", () -> redis.getMappedPort(6379).toString());
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## @DataJpaTest Patterns
|
|
106
|
+
|
|
107
|
+
### Repository CRUD
|
|
108
|
+
```java
|
|
109
|
+
@DataJpaTest
|
|
110
|
+
class UserRepositoryTest {
|
|
111
|
+
@Autowired UserRepository repository;
|
|
112
|
+
|
|
113
|
+
@Test
|
|
114
|
+
void saveAndFind() {
|
|
115
|
+
User user = new User("John", "john@example.com");
|
|
116
|
+
User saved = repository.save(user);
|
|
117
|
+
assertThat(repository.findById(saved.getId())).isPresent();
|
|
118
|
+
assertThat(repository.findAll()).hasSize(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Test
|
|
122
|
+
void findByEmail() {
|
|
123
|
+
repository.save(new User("John", "john@example.com"));
|
|
124
|
+
assertThat(repository.findByEmail("john@example.com")).isPresent();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### With TestContainers
|
|
130
|
+
```java
|
|
131
|
+
@DataJpaTest
|
|
132
|
+
@Testcontainers
|
|
133
|
+
class UserRepositoryTest {
|
|
134
|
+
@Container
|
|
135
|
+
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
|
|
136
|
+
|
|
137
|
+
@DynamicPropertySource
|
|
138
|
+
static void configure(DynamicPropertyRegistry registry) {
|
|
139
|
+
registry.add("spring.datasource.url", postgres::getJdbcUrl);
|
|
140
|
+
registry.add("spring.datasource.username", postgres::getUsername);
|
|
141
|
+
registry.add("spring.datasource.password", postgres::getPassword);
|
|
142
|
+
}
|
|
143
|
+
// ...
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## WebTestClient Patterns
|
|
148
|
+
|
|
149
|
+
### Bind to Controller (no full context)
|
|
150
|
+
```java
|
|
151
|
+
@ExtendWith(MockitoExtension.class)
|
|
152
|
+
class UserControllerTest {
|
|
153
|
+
@Mock UserService userService;
|
|
154
|
+
WebTestClient webTestClient;
|
|
155
|
+
|
|
156
|
+
@BeforeEach
|
|
157
|
+
void setUp() {
|
|
158
|
+
webTestClient = WebTestClient.bindToController(new UserController(userService)).build();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@Test
|
|
162
|
+
void getUsers_returnsOk() {
|
|
163
|
+
when(userService.findAll()).thenReturn(List.of(new User(1L, "John")));
|
|
164
|
+
webTestClient.get().uri("/api/users")
|
|
165
|
+
.exchange()
|
|
166
|
+
.expectStatus().isOk()
|
|
167
|
+
.expectBodyList(User.class).hasSize(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Full Application (integration)
|
|
173
|
+
```java
|
|
174
|
+
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
|
175
|
+
class UserControllerIntegrationTest {
|
|
176
|
+
@Autowired WebTestClient webTestClient;
|
|
177
|
+
|
|
178
|
+
@Test
|
|
179
|
+
void getUsers_returnsOk() {
|
|
180
|
+
webTestClient.get().uri("/api/users")
|
|
181
|
+
.exchange()
|
|
182
|
+
.expectStatus().isOk()
|
|
183
|
+
.expectBody()
|
|
184
|
+
.jsonPath("$").isArray();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## @MockBean Patterns
|
|
190
|
+
|
|
191
|
+
### Mock Service in Integration Test
|
|
192
|
+
```java
|
|
193
|
+
@SpringBootTest
|
|
194
|
+
@AutoConfigureMockMvc
|
|
195
|
+
class OrderControllerIntegrationTest {
|
|
196
|
+
@Autowired MockMvc mockMvc;
|
|
197
|
+
@MockBean PaymentService paymentService;
|
|
198
|
+
|
|
199
|
+
@Test
|
|
200
|
+
void createOrder_mocksPayment() throws Exception {
|
|
201
|
+
when(paymentService.process(any())).thenReturn(new PaymentResult("ok", "tx-123"));
|
|
202
|
+
mockMvc.perform(post("/api/orders").contentType(JSON).content(orderJson))
|
|
203
|
+
.andExpect(status().isCreated());
|
|
204
|
+
verify(paymentService).process(any());
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## @Transactional and Data Cleanup
|
|
210
|
+
|
|
211
|
+
```java
|
|
212
|
+
@SpringBootTest
|
|
213
|
+
@Transactional // Rollback after each test
|
|
214
|
+
class OrderServiceIntegrationTest {
|
|
215
|
+
@Autowired OrderRepository orderRepository;
|
|
216
|
+
|
|
217
|
+
@Test
|
|
218
|
+
void createOrder_persists() {
|
|
219
|
+
orderRepository.save(new Order(...));
|
|
220
|
+
assertThat(orderRepository.count()).isEqualTo(1);
|
|
221
|
+
// Rolled back automatically after test
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## @TestPropertySource
|
|
227
|
+
|
|
228
|
+
```java
|
|
229
|
+
@SpringBootTest
|
|
230
|
+
@TestPropertySource(properties = {
|
|
231
|
+
"app.feature.enabled=true",
|
|
232
|
+
"spring.jpa.hibernate.ddl-auto=create-drop"
|
|
233
|
+
})
|
|
234
|
+
class FeatureIntegrationTest { }
|
|
235
|
+
```
|