在 Java 中,DAO(Data Access Object)层测试的核心目标是:
验证 DAO 是否能正确地与数据库进行增删改查,而不依赖业务逻辑。
下面从 测试策略、常见方式、示例代码、最佳实践 四个方面系统说明。
✅ 结论:
DAO 单元测试通常 = 使用内存数据库的集成测试
✅ 这是 DAO 测试的主流方式
| 方式 | 是否推荐 | 说明 |
|---|---|---|
| Mock DAO | ❌ 不推荐 | 测不到 SQL / ORM |
| 内存数据库(H2) | ✅ 强烈推荐 | 快速、可自动化 |
| Testcontainers | ✅ 推荐 | 接近真实数据库 |
| 真实数据库 | ⚠️ 谨慎 | 慢、环境依赖强 |
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByAgeGreaterThan(int age);
}
@SpringBootTest
@Transactional
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldFindUsersByAge() {
User user = new User();
user.setName("Tom");
user.setAge(20);
userRepository.save(user);
List<User> result = userRepository.findByAgeGreaterThan(18);
assertThat(result).isNotEmpty();
assertThat(result.get(0).getName()).isEqualTo("Tom");
}
}
✅ 特点:
@Transactional:测试结束自动回滚@Mapper
public interface UserDao {
User selectById(Long id);
void insert(User user);
}
@SpringBootTest
@Transactional
class UserDaoTest {
@Autowired
private UserDao userDao;
@Test
void shouldInsertAndSelectUser() {
User user = new User();
user.setName("Alice");
userDao.insert(user);
User result = userDao.selectById(user.getId());
assertThat(result).isNotNull();
assertThat(result.getName()).isEqualTo("Alice");
}
}
适合:
@TestConfiguration
public class TestcontainersConfig {
@Bean
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("test")
.withUsername("test")
.withPassword("test");
}
}
✅ 优点:
❌ 缺点:
save
findById
update
delete
@Transactional
@Rollback
❌ 不推荐:
assert sql.contains("select");
✅ 推荐:
assertThat(result.size()).isEqualTo(1);
DAO 的意义就是访问数据库
Mock 它 = 什么都没测
| 误区 | 说明 |
|---|---|
| Mock EntityManager | 测不到 ORM |
| 只测 save | 不测查询 |
| 使用真实库但不清理 | 测试互相影响 |
| 不校验数据一致性 | 只是“跑通” |
DAO 测试 = 用真实(或接近真实)数据库,验证数据存取是否正确。
如果你愿意,可以告诉我:
我可以帮你写 完全贴合你项目的 DAO 测试用例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。