java-testing-advanced

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Java Testing Advanced Skill

Java高级测试技能

Advanced testing techniques for comprehensive test coverage.
实现全面测试覆盖的高级测试技术。

Overview

概述

This skill covers advanced testing patterns including Testcontainers for integration testing, contract testing with Pact, mutation testing with PIT, and property-based testing.
本技能涵盖了多种高级测试模式,包括用于集成测试的Testcontainers、基于Pact的契约测试、基于PIT的变异测试以及基于属性的测试。

When to Use This Skill

适用场景

Use when you need to:
  • Test with real databases (Testcontainers)
  • Verify API contracts
  • Find gaps with mutation testing
  • Generate test cases automatically
当你需要以下操作时使用本技能:
  • 使用真实数据库进行测试(Testcontainers)
  • 验证API契约
  • 通过变异测试发现测试覆盖缺口
  • 自动生成测试用例

Quick Reference

快速参考

Testcontainers

Testcontainers

java
@Testcontainers
@SpringBootTest
class OrderRepositoryIT {

    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:15")
            .withDatabaseName("test")
            .withUsername("test")
            .withPassword("test");

    @Container
    static KafkaContainer kafka =
        new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0"));

    @DynamicPropertySource
    static void configure(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
    }

    @Test
    void shouldPersistOrder() {
        Order saved = repository.save(new Order("item", 100.0));
        assertThat(saved.getId()).isNotNull();
    }
}
java
@Testcontainers
@SpringBootTest
class OrderRepositoryIT {

    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:15")
            .withDatabaseName("test")
            .withUsername("test")
            .withPassword("test");

    @Container
    static KafkaContainer kafka =
        new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0"));

    @DynamicPropertySource
    static void configure(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
    }

    @Test
    void shouldPersistOrder() {
        Order saved = repository.save(new Order("item", 100.0));
        assertThat(saved.getId()).isNotNull();
    }
}

Contract Testing (Pact)

契约测试(Pact)

java
@ExtendWith(PactConsumerTestExt.class)
class UserServiceContractTest {

    @Pact(consumer = "order-service", provider = "user-service")
    public RequestResponsePact createPact(PactDslWithProvider builder) {
        return builder
            .given("user exists")
            .uponReceiving("get user request")
                .path("/users/1")
                .method("GET")
            .willRespondWith()
                .status(200)
                .body(new PactDslJsonBody()
                    .integerType("id", 1)
                    .stringType("name", "John"))
            .toPact();
    }

    @Test
    @PactTestFor(pactMethod = "createPact")
    void testGetUser(MockServer mockServer) {
        User user = client.getUser(mockServer.getUrl(), 1L);
        assertThat(user.getName()).isEqualTo("John");
    }
}
java
@ExtendWith(PactConsumerTestExt.class)
class UserServiceContractTest {

    @Pact(consumer = "order-service", provider = "user-service")
    public RequestResponsePact createPact(PactDslWithProvider builder) {
        return builder
            .given("user exists")
            .uponReceiving("get user request")
                .path("/users/1")
                .method("GET")
            .willRespondWith()
                .status(200)
                .body(new PactDslJsonBody()
                    .integerType("id", 1)
                    .stringType("name", "John"))
            .toPact();
    }

    @Test
    @PactTestFor(pactMethod = "createPact")
    void testGetUser(MockServer mockServer) {
        User user = client.getUser(mockServer.getUrl(), 1L);
        assertThat(user.getName()).isEqualTo("John");
    }
}

Mutation Testing (PIT)

变异测试(PIT)

xml
<plugin>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-maven</artifactId>
    <version>1.15.0</version>
    <configuration>
        <targetClasses>
            <param>com.example.service.*</param>
        </targetClasses>
        <mutationThreshold>80</mutationThreshold>
    </configuration>
</plugin>
xml
<plugin>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-maven</artifactId>
    <version>1.15.0</version>
    <configuration>
        <targetClasses>
            <param>com.example.service.*</param>
        </targetClasses>
        <mutationThreshold>80</mutationThreshold>
    </configuration>
</plugin>

Property-Based Testing

基于属性的测试

java
@Property
void shouldReverseListTwiceReturnsOriginal(@ForAll List<Integer> list) {
    Collections.reverse(list);
    Collections.reverse(list);
    // Original order restored
}
java
@Property
void shouldReverseListTwiceReturnsOriginal(@ForAll List<Integer> list) {
    Collections.reverse(list);
    Collections.reverse(list);
    // Original order restored
}

Testing Pyramid

测试金字塔

     /\        E2E Tests (few)
    /  \       Contract Tests
   /----\      Integration Tests
  /------\     Unit Tests (many)
     /\        E2E Tests (few)
    /  \       Contract Tests
   /----\      Integration Tests
  /------\     Unit Tests (many)

Troubleshooting

故障排除

ProblemSolution
Container slowReuse containers
Port conflictsRandom ports
Flaky testsWait strategies
问题解决方案
容器运行缓慢复用容器
端口冲突使用随机端口
不稳定的测试使用等待策略

Usage

使用方法

Skill("java-testing-advanced")
Skill("java-testing-advanced")