我们有很多类似如下的连接和提取方法:
@Query(
"select new com.vulog.user.entity.DTO.UserBillingDTO(" +
"u.id as id, " +
"u.firstName as firstName, " +
"u.lastName as lastName, " +
"e.tokenId as billingTokenID," +
"u.fleetId as fleetId," +
"e.id as entityId, " +
"u.userName as userName, " +
"u.locale as locale) " +
"from User as u " +
"join u.profiles as p " +
"join p.entity as e " +
"where u.id = :userId")
UserBillingDTO findUserForBilling(@Param("userId") String userId);
我想在测试中介绍此类方法,并查看我们的HQL查询是否返回了预期的结果。
问题是我如何才能轻松地填充本地数据库以测试我们方法的结果?
您还能想到其他吗?我该如何编写一个易于维护的,易于团队使用的测试套件?
编辑:
答案 0 :(得分:1)
如果您不使用数据库特定的功能,例如自定义特定于Oracle的SQL函数,您可以在@SpringBootTest
测试中设置嵌入式数据库。使用@AutoConfigureTestDatabase
注释对测试类进行注释,例如将默认应用程序DataSource
bean替换为嵌入式内存数据库:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
您可以根据81.5 Use a Higher-level Database Migration Tool章使用Flyway或Liquibase来填充数据库。根据文档:
您还可以使用Flyway为特定情况提供数据。例如,您可以将特定于测试的迁移放置在src / test / resources中,并且仅在您的应用程序开始进行测试时才运行它们。另外,您可以使用特定于配置文件的配置来自定义spring.flyway.locations,以便仅在特定配置文件处于活动状态时才运行某些迁移。例如,在application-dev.properties中,您可以指定以下设置:
答案 1 :(得分:1)
一种可能性是在测试中创建记录。这就是您所描述的显而易见的解决方案。对于当前代码,您可以执行以下操作:
@Test
public void findUserForBilling() {
repository.saveAll(Lists.newArrayList(
new User("1", "John", "Doe", "JDoe123", new Profile(..., new ProfileEntity(1, "token123"))),
new User("2", "Jane", "Doe", "TheJane", new Profile(..., new ProfileEntity(2, "token234")))));
UserBillingDTO dto = repository.findUserForBilling("1");
assertThat(dto.getId()).isEqualTo("1");
// ...
}
尽管在某些情况下,您的测试数据可能会占据一定的位置,但在这种情况下,它仅占几行,仅比通常的单元测试准备/给定方案多。
请注意:在这种类型的测试中,您并未测试实体映射。如果您的实体映射中存在问题,您将无法判断使用这些测试。
另一种可能性是使用单独的SQL文件,例如user-dataset.sql
中的src/test/resources
:
insert into user (id, firstname, lastname) values ("1", "John", "Doe");
insert into user (id, firstname, lastname) values ("2", "Jane", "Doe");
--- ...
然后您可以使用@Sql
批注将该数据集包含在测试中,例如:
@RunWith(SpringRunner.class)
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Sql("classpath:user-dataset.sql") // Add this
public class UserRepositoryTest {
// ...
}
您可以将@Sql
批注添加到测试类,甚至添加到单个测试方法,例如:
@Test
@Sql("classpath:user-dataset.sql") // Add this
public void findUserForBilling() {
UserBillingDTO dto = repository.findUserForBilling("1");
assertThat(dto.getId()).isEqualTo("1");
// ...
}
注意:如果我没记错的话,Spring将为测试类创建一次数据源。如果您为每种测试方法执行数据集,则必须添加
delete
语句以首先删除所有现有记录。
如果只希望一个数据集用于所有测试,则可以进一步简化和命名数据集data.sql
。如果使用内存数据库(这可能对测试有用),由于Spring Boot将在类路径上自动执行data.sql
文件,因此您甚至不需要@Sql
批注。
另一种方法是选择类似DbUnit的框架,该框架允许您以XML格式定义数据集。您可以将其与Spring Test DBUnit结合使用,以更轻松地与Spring集成。
您必须牢记,尽管设置起来不像使用@Sql
那样容易,并且您需要了解另一种语言,即用于设置数据集的XML结构。