一键导入
uw-analyze-integration-tests
Use when analyzing integration tests that verify component interactions, database access, and external service integration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when analyzing integration tests that verify component interactions, database access, and external service integration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use after unwind:uw-plan to EXECUTE the rebuild — interview the user about scope/order/target, dispatch technology-agnostic per-layer builder agents that reproduce the [MUST] contracts in the target stack, hold rebuild state in a local file, and maintain a source→target verification graph that measures completeness. Supports a loop-until-verified mode.
Use to visually explore the rebuild knowledge graph. Builds and launches the Unwind dashboard (React + React Flow + ELK) pointed at docs/unwind/rebuild-graph.json with coverage, priority, and contract views.
Optional. Publish the Unwind dashboard to the scanned project's GitHub Pages gh-pages branch so it's viewable at https://<owner>.github.io/<repo>/unwind/. Builds the dashboard at the correct sub-path and commits it into an `unwind/` subdir — never blatting an existing gh-pages branch. Confirms the target, then pushes.
Use when dispatched by unwind:uw-build to rebuild ONE layer/slice of a codebase in the target stack. Technology-agnostic builder that reproduces the layer's [MUST] contracts (API surface, data model, business rules) as idiomatic target-stack code and records the source→target mapping for verification.
Use when starting any reverse engineering task - establishes how to find and use Unwind skills for codebase analysis, service mapping, and documentation
Use after layer analysis is complete to interview the user about the rebuild strategy (target stack, what to keep vs rebuild, phasing, risk) and generate a data-grounded REBUILD-PLAN.md that records those decisions.
| name | uw-analyze-integration-tests |
| description | Use when analyzing integration tests that verify component interactions, database access, and external service integration |
| allowed-tools | ["Read","Grep","Glob","Bash(mkdir:*, ls:*)","Write(docs/unwind/**)","Edit(docs/unwind/**)"] |
Output: docs/unwind/layers/integration-tests/ (folder with index.md + section files)
Principles: See analysis-principles.md - completeness, machine-readable, link to source, no commentary, incremental writes.
docs/unwind/layers/integration-tests/
├── index.md # Test summary, infrastructure overview
├── config.md # Test containers, database setup
├── repository-tests.md # Database integration tests
├── api-tests.md # API endpoint tests
├── external-tests.md # External service integration tests
└── messaging-tests.md # Kafka/queue tests
For large codebases, split by integration type:
docs/unwind/layers/integration-tests/
├── index.md
├── config.md
├── database/
├── api/
└── messaging/
Step 1: Setup
mkdir -p docs/unwind/layers/integration-tests/
Write initial index.md:
# Integration Tests
## Sections
- [Configuration](config.md) - _pending_
- [Repository Tests](repository-tests.md) - _pending_
- [API Tests](api-tests.md) - _pending_
- [External Service Tests](external-tests.md) - _pending_
- [Messaging Tests](messaging-tests.md) - _pending_
## Summary
_Analysis in progress..._
Step 2: Analyze and write config.md
config.md immediatelyindex.mdStep 3: Analyze and write repository-tests.md
repository-tests.md immediatelyindex.mdStep 4: Analyze and write api-tests.md
api-tests.md immediatelyindex.mdStep 5: Analyze and write external-tests.md (if applicable)
external-tests.md immediatelyindex.mdStep 6: Analyze and write messaging-tests.md (if applicable)
messaging-tests.md immediatelyindex.mdStep 7: Finalize index.md Add integration summary table
# Integration Tests
## Configuration
### Test Containers
[TestContainersConfig.java](https://github.com/owner/repo/blob/main/src/test/java/config/TestContainersConfig.java)
```java
@TestConfiguration
public class TestContainersConfig {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@Container
static KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.0.0"));
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
}
}
@TestConfiguration
public class WireMockConfig {
@Bean
public WireMockServer wireMockServer() {
WireMockServer server = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort());
server.start();
return server;
}
}
| Integration | Tests | Status |
|---|---|---|
| Database | 15 | Passing |
| Kafka | 8 | Passing |
| Stripe API | 5 | Passing |
| Email Service | 3 | Passing |
@DataJpaTest
@Testcontainers
@AutoConfigureTestDatabase(replace = NONE)
class UserRepositoryIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14");
@Autowired
private UserRepository userRepository;
@Test
void findByEmail_existingUser_returnsUser() {
User user = new User("test@example.com", "hash");
userRepository.save(user);
Optional<User> found = userRepository.findByEmail("test@example.com");
assertThat(found).isPresent();
assertThat(found.get().getEmail()).isEqualTo("test@example.com");
}
@Test
void findByStatus_multipleUsers_returnsFiltered() {
userRepository.save(new User("active@example.com", "hash", UserStatus.ACTIVE));
userRepository.save(new User("suspended@example.com", "hash", UserStatus.SUSPENDED));
List<User> active = userRepository.findByStatus(UserStatus.ACTIVE);
assertThat(active).hasSize(1);
assertThat(active.get(0).getEmail()).isEqualTo("active@example.com");
}
}
[Continue for ALL repository tests...]
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Testcontainers
class UserControllerIT {
@Autowired
private TestRestTemplate restTemplate;
@Test
void createUser_validRequest_returnsCreated() {
CreateUserRequest request = new CreateUserRequest("new@example.com", "password123", "New User");
ResponseEntity<UserResponse> response = restTemplate.postForEntity(
"/api/v1/users", request, UserResponse.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
assertThat(response.getBody().email()).isEqualTo("new@example.com");
}
}
@SpringBootTest
@AutoConfigureWireMock(port = 0)
class StripeClientIT {
@Autowired
private StripeClient stripeClient;
@Test
void charge_validToken_returnsSuccess() {
stubFor(post(urlEqualTo("/v1/charges"))
.willReturn(aResponse()
.withStatus(200)
.withBody("{\"id\": \"ch_123\", \"status\": \"succeeded\"}")));
PaymentResult result = stripeClient.charge("tok_valid", Money.of(100, USD));
assertThat(result.isSuccess()).isTrue();
}
}
@SpringBootTest
@EmbeddedKafka(partitions = 1, topics = {"order-events"})
class OrderEventIT {
@Autowired
private OrderEventPublisher publisher;
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
@Test
void publishOrderCreated_sendsToKafka() {
Order order = createTestOrder();
publisher.publishOrderCreated(order);
// Verify message received
ConsumerRecord<String, Object> record = KafkaTestUtils.getSingleRecord(consumer, "order-events");
assertThat(record.value()).isInstanceOf(OrderCreatedEvent.class);
}
}
## Refresh Mode
If `docs/unwind/layers/integration-tests/` exists, compare current state and add `## Changes Since Last Review` section to `index.md`.