英文:
Spring `JpaRepository` to be used only in test scope
问题
我有一个`JpaRepository`,看起来像这样:
```java
@Repository
public interface CustomRepository extends JpaRepository<EntityType, Integer> {
// 方法
}
可能会有一些可能运行很长时间的查询,这种情况下我需要强制执行超时。我已经成功添加了与超时相关的配置(如果使用的连接池是Druid
,可能会有所影响),现在我想在单元测试中对其进行测试。我在我的JpaRepository<T, ID>
接口中使用了以下方法:
@Query(value = "SELECT benchmark(:count, MD5('3094803'))", nativeQuery = true)
void run(@Param("count") Long count);
这个方法成功运行并展示了预期的行为。然而,考虑到这个方法的运行时间会随着参数count
的增加而变长,仅出于测试超时的目的就将其放在生产代码中,让我感到非常不舒服,因为这可能最终会成为一个可以被利用发起拒绝服务攻击的漏洞。
因此,针对这个问题,是否有办法在我的测试范围内使用这个完全相同的方法,而不必将其放入生产代码中?
<details>
<summary>英文:</summary>
I have a `JpaRepository`, that looks like
@Repository
public interface CustomRepository extends JpaRepository<EntityType, Integer> {
// Methods
}
which could possibly have queries that would run for long, in which case I need to enforce a timeout. I have successfully added the timeout-related configuration (the connection pool being used is `Druid`, if that matters) and now I want to test it in a unit test. I am using the following method in my `JpaRepository<T, ID>` interface.
@Query(value = "SELECT benchmark(:count, MD5('3094803'))", nativeQuery = true)
void run(@Param("count") Long count);
This method runs successfully and demonstrates the expected behavior. However, given that this method will run longer as the value given to parameter `count` becomes larger, having this in the production code, just for the sake of testing the timeouts, bothers me to my core, as this might end up being a vulnerability that could be leveraged to launch a denial attack.
So to the question, is some way I can use this exact method in my test scope, without having that going in the production code?
</details>
# 答案1
**得分**: 0
结果证明,事情并不是那么复杂。考虑到这个项目是在 Spring 上运行的,我可以在我的测试源代码中扩展上面的存储库,如下所示。
```java
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 Boot 上运行的测试类,如下所示。
package com.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") // 数据源连接;不是很重要。
public class TransactionHistoryJpaRepoTest {
@Autowired //---(1)
private TimedCustomRepository timedCustomRepository;
@Test(expected = JpaSystemException.class)
public void whenQueryTimeoutOccurs() {
timedCustomRepository.run(100000000L);
}
}
在 (1)
处的属性将使用我们上面创建的存储库 bean 进行连接,这个测试将如预期般执行。由于 TimedCustomRepository
这个 bean 扩展了 CustomRepository
,数据源配置和其他所有内容都将保持相同。最重要的是,由于这个包含长时间运行查询的方法现在仅在测试范围内,它不会对测试范围之外产生任何影响。
英文:
Turns out, it's not that complicated. Given that this project is running on Spring, I can have an extension of the above repository in my test sources, as follows.
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);
}
As I have JUnit4, I can have a test class which will run on Spring boot, like follows.
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);
}
}
The property at (1)
will be wired using the repository bean which we have created above, and this test will execute as expected. Given the bean TimedCustomRepository
extends CustomRepository
, the data source configuration and everything will be the same. Most importantly, since this method with a long running query is now only on the test scope, it will not have any impact beyond the test scope.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论