AssertJ流式断言与Testcontainers集成测试
请详细解释AssertJ流式断言库的优势和常用API,以及Testcontainers如何为集成测试提供数据库/中间件等依赖的Docker容器支持。如何组合使用AssertJ和Testcontainers编写高质量集成测试?
回答
苦行僧
AssertJ流式断言
优势:可读性强、类型安全、丰富的断言方法、链式调用
import static org.assertj.core.api.Assertions.*;
// 基础断言
assertThat("Hello World")
.isNotEmpty()
.startsWith("Hello")
.contains("World")
.endsWith("ld");
// 集合断言
assertThat(list)
.hasSize(3)
.contains("a", "b")
.doesNotContain("z")
.allMatch(s -> s.length() > 0)
.anyMatch("c"::equals);
// 异常断言
assertThatThrownBy(() -> { throw new RuntimeException("error"); })
.isInstanceOf(RuntimeException.class)
.hasMessage("error")
.hasNoCause();
// Optional断言
assertThat(Optional.of("value"))
.isPresent()
.hasValue("value");
// 自定义比较
assertThat(person).usingRecursiveComparison()
.ignoringFields("id", "createdAt")
.isEqualTo(expectedPerson);
Testcontainers集成测试
核心概念:在JUnit测试中启动Docker容器,测试结束后自动销毁。
@Testcontainers
class UserRepositoryTest {
// 静态容器(所有测试共享)
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
// 动态属性注入
@DynamicPropertySource
static void configure(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
// 模块化容器
@Container
static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
.withExposedPorts(6379);
}
支持的容器:PostgreSQL、MySQL、Redis、Kafka、Elasticsearch、MinIO等
组合使用
@Test
void testUserCreation() {
// Testcontainers提供真实DB
userService.createUser(new User("test@example.com"));
// AssertJ验证结果
assertThat(userRepository.findByEmail("test@example.com"))
.isPresent()
.get()
.extracting(User::getEmail, User::isActive)
.containsExactly("test@example.com", true);
}