我花了很多时间来识别以下 JPQL 连接查询的单元测试用例。以下是我的实施细节。我找不到为存储库层编写测试用例的正确方法。
存储库类
@Repository
public interface UserRepository extends JPARepository<User, Integer> {
@Query("select u from User u join fetch u.venues uv where u.eventId = :eventId")
User findUserByEventId(String eventId);
......
}
用户类别
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
private String firstName;
private String lastName;
@OneToMany(targetEntity = UserVenues.class, mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<UserVenues> venues;
private String eventId;
......
}
用户场地
public class UserVenues{
@Id
private int id;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "user_Id", referencedColumnName = "id")
private User user;
......
}
我热切期待解决方案。
因此,如果您想测试一些 JPQL 查询,我认为在这里编写简单的单元测试可能没有帮助。您将需要
hibernate-core
将 JPQL 渲染为 SQL、执行查询、映射结果等。模拟所有这些都是不切实际的。
所以我认为在这种情况下,与数据库进行集成测试是最合适的。您可以使用 H2 设置测试数据库 ,也可以使用 testcontainers。由于您使用的是 JPQL,因此这两种方法应该都能很好地工作,尽管我仍然建议使用 testcontainers 以避免在 H2 道路上遇到不同的兼容性问题。
因此,设置测试容器后,您可以执行以下操作:
@SpringBootTest
public class MyIntegrationTest {
@Autowired
private UserRepository userRepository;
@Autowired
private DataSource dataSource;
@BeforeEach
void setUp() throws SQLException {
ScriptUtils.executeSqlScript(
dataSource.getConnection(),
new ByteArrayResource("""
DELETE FROM user_venues;
DELETE FROM users;
INSERT INTO users(first_name, last_name. event_id) VALUES('bob', 'wasowski', '123');
INSERT INTO user_venues(id, user_id) VALUES(1, (SELECT id FROM users WHERE event_id = '123' LIMIT 1));
""".getBytes())
);
}
@Test
void testJoinQuery() {
User something = userRepository.findUserByEventId("something");
Assertions.assertThat(something).extracting(User::getFirstName).isEqualTo("Bob");
Assertions.assertThat(something).extracting(it -> it.getVenues().size()).isEqualTo(2);
}
}
严格来说,
@SpringBootTest
并不是那么必要,如果您只想测试存储库层,@DataJpaTest
或类似的东西就足够了。 这又只是一个示例,在现实世界中,我强烈建议您将 init sql 查询提取到单独的文件等中。这仅供您用于演示目的。因此考虑使用 Spring Boot 来为此任务编写一个集成测试。
希望有帮助:)
P.S:我想定义
UserRepository
有点错误 - 如果你想查询JpaRepository<User, Long>
实体,你应该扩展User
(注意第一个类型参数)。