问题描述
我有一个JpaRepository
,看起来像
@Repository
public interface CustomRepository extends JpaRepository<EntityType,Integer> {
// Methods
}
可能会有长时间运行的查询,在这种情况下,我需要执行超时。我已经成功添加了与超时相关的配置(如果使用的话,连接池是Druid
),现在我想在单元测试中对其进行测试。我在JpaRepository<T,ID>
界面中使用以下方法。
@Query(value = "SELECT benchmark(:count,MD5('3094803'))",nativeQuery = true)
void run(@Param("count") Long count);
此方法成功运行,并演示了预期的行为。但是,由于此方法将随着参数count
的值变大而运行更长的时间,并且在生产代码中具有此值,仅出于测试超时的目的,这使我感到烦恼,因为这可能最终是可以用来发起拒绝攻击的漏洞。
问题是,有什么方法可以在测试范围内使用此确切方法,而不必在生产代码中使用?
解决方法
结果证明,它并不那么复杂。鉴于该项目正在Spring上运行,我可以在测试源中扩展上述存储库,如下所示。
package com.project.package.repo;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface TimedCustomRepository extends CustomRepository {
@Query(value = "SELECT benchmark(:count,MD5('3094803'))",nativeQuery = true)
void run(@Param("count") Long count);
}
有了JUnit4,我可以拥有一个将在Spring启动时运行的测试类,如下所示。
package om.project.package.repo;
import com.github.database.rider.spring.api.DBRider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
@RunWith(SpringRunner.class)
@DBRider(dataSourceBeanName = "primaryDataSource") //Data source wiring; Not that important.
public class TransactionHistoryJpaRepoTest {
@Autowired //---(1)
private TimedCustomRepository timedCustomRepository;
@Test(expected = JpaSystemException.class)
public void whenQueryTimeoutOccurs() {
timedCustomRepository.run(100000000L);
}
}
(1)
处的属性将使用上面创建的存储库bean进行连接,并且此测试将按预期执行。假设bean TimedCustomRepository
扩展了CustomRepository
,则数据源配置和所有内容都将相同。最重要的是,由于此方法具有长时间运行的查询,现在仅在测试范围内,因此对测试范围没有任何影响。